├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── dictionaries │ └── zzk.xml ├── encodings.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── libs │ └── jsoup-1.8.3.jar ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── lico │ │ └── example │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── lico │ │ │ └── example │ │ │ ├── adapter │ │ │ ├── BaseAdapterHelper.java │ │ │ ├── BaseQuickAdapter.java │ │ │ ├── ContentPagerAdapter.java │ │ │ ├── SimpleRecyclerAdapter.java │ │ │ └── TabFragmentPagerAdapter.java │ │ │ ├── app │ │ │ └── EApplication.java │ │ │ ├── bean │ │ │ ├── HttpResponseEntity.java │ │ │ ├── ImagesListEntity.java │ │ │ ├── JcodeInfo.java │ │ │ └── ResponseImagesListEntity.java │ │ │ ├── fragment │ │ │ ├── ContentFragment.java │ │ │ ├── ContentListFragment.java │ │ │ ├── ImageFragment.java │ │ │ ├── ImageListFragment.java │ │ │ └── LazyFragment.java │ │ │ ├── helper │ │ │ ├── EventHelper.java │ │ │ └── GenericHelper.java │ │ │ ├── listener │ │ │ ├── HttpApi.java │ │ │ └── JSONParserCompleteListener.java │ │ │ ├── presenter │ │ │ ├── ActivityPresenter.java │ │ │ ├── FragmentPresenter.java │ │ │ └── IPresenter.java │ │ │ ├── ui │ │ │ ├── MainActivity.java │ │ │ ├── PersonalActivity.java │ │ │ └── SpaceImageDetailActivity.java │ │ │ ├── utils │ │ │ ├── BitmapUtil.java │ │ │ └── DataUtil.java │ │ │ ├── view │ │ │ ├── ContentView.java │ │ │ ├── ContentlistView.java │ │ │ ├── IView.java │ │ │ ├── ImageListView.java │ │ │ ├── ImagesView.java │ │ │ ├── MainView.java │ │ │ ├── PersonalView.java │ │ │ └── ViewImpl.java │ │ │ └── views │ │ │ ├── PLAImageView.java │ │ │ ├── PullLoadMoreRecyclerView.java │ │ │ ├── RecyclerViewOnScroll.java │ │ │ ├── SmoothImageView.java │ │ │ ├── SpacesItemDecoration.java │ │ │ ├── SuperRecyclerView.java │ │ │ └── SwipeRefreshLayoutOnRefresh.java │ └── res │ │ ├── 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 │ │ ├── activated_background.xml │ │ ├── selectable_background.xml │ │ └── side_nav_bar.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── activity_personal.xml │ │ ├── activity_test.xml │ │ ├── app_bar_main.xml │ │ ├── content_main.xml │ │ ├── fragment_content.xml │ │ ├── fragment_content_list.xml │ │ ├── fragment_image.xml │ │ ├── fragment_image_list.xml │ │ ├── fragment_images.xml │ │ ├── nav_header_main.xml │ │ ├── toolbar_layout.xml │ │ ├── view_content_list.xml │ │ ├── view_footer.xml │ │ ├── view_image_list_item.xml │ │ └── view_pull_load_more.xml │ │ ├── menu │ │ ├── activity_main_drawer.xml │ │ └── main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ ├── avator.jpg │ │ ├── bg_banner_dialog.jpg │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_discuss.png │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-v21 │ │ └── styles.xml │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── arrays.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── drawables.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── lico │ └── example │ └── 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/.name: -------------------------------------------------------------------------------- 1 | MVPExample -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/dictionaries/zzk.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 23 | 24 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MVPExample 2 | 改良版MVP的demo; 涉及技术MVP activity模型、fragment模型(懒加载) 、retrofit 2.0 rxjava简单应用 3 | 4 | 项目中图片资源参考了简阅代码https://github.com/SkillCollege/SimplifyReader 5 | 6 | 因为电脑丢失:有些参考资料已经不记得了; 7 | 8 | 参考资料:http://kymjs.com/code/2015/11/09/01/ 9 | 10 | http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0915/3460.html 11 | 12 | https://github.com/lzyzsd/Awesome-RxJava中各种 13 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'me.tatarka.retrolambda' 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.2" 6 | 7 | defaultConfig { 8 | applicationId "lico.example" 9 | minSdkVersion 11 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | compileOptions{ 21 | sourceCompatibility 1.8 22 | targetCompatibility 1.8 23 | } 24 | } 25 | 26 | 27 | 28 | dependencies { 29 | compile fileTree(include: ['*.jar'], dir: 'libs') 30 | compile 'com.android.support:appcompat-v7:23.1.1' 31 | compile 'com.android.support:design:23.1.1' 32 | compile 'com.jakewharton:butterknife:7.0.0' 33 | compile 'io.reactivex:rxandroid:1.0.0' 34 | compile 'com.squareup.retrofit:retrofit:2.0.0-beta1' 35 | compile 'com.squareup.retrofit:converter-gson:2.0.0-beta1' 36 | compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta1' 37 | compile 'com.google.code.gson:gson:2.3.1' 38 | compile 'com.squareup.okhttp:okhttp:2.4.0' 39 | compile 'com.jcodecraeer:xrecyclerview:1.2.5' 40 | compile 'com.github.bumptech.glide:glide:3.6.0' 41 | debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3' 42 | releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3' 43 | compile 'com.android.support:cardview-v7:23.1.1' 44 | compile 'com.facebook.fresco:fresco:0.8.1+' 45 | compile files('libs/jsoup-1.8.3.jar') 46 | } 47 | -------------------------------------------------------------------------------- /app/libs/jsoup-1.8.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzkong/MVPExample/dfe591ab976120b811cb5bc792a4b6cd9045f6d2/app/libs/jsoup-1.8.3.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 /Users/zzk/Library/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/lico/example/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package lico.example; 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 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 28 | 29 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/adapter/BaseAdapterHelper.java: -------------------------------------------------------------------------------- 1 | package lico.example.adapter; 2 | 3 | import android.net.Uri; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.util.SparseArray; 6 | import android.view.View; 7 | import android.widget.Button; 8 | import android.widget.ImageView; 9 | import android.widget.TextView; 10 | 11 | import com.bumptech.glide.Glide; 12 | import com.facebook.drawee.view.SimpleDraweeView; 13 | 14 | import lico.example.app.EApplication; 15 | import lico.example.views.PLAImageView; 16 | 17 | 18 | /** 19 | * Created by zwl on 2015/8/25. 20 | */ 21 | public class BaseAdapterHelper extends RecyclerView.ViewHolder { 22 | 23 | private SparseArray views; 24 | 25 | 26 | public BaseAdapterHelper(View itemView) { 27 | super(itemView); 28 | this.views = new SparseArray(); 29 | } 30 | 31 | public void setText(int viewId, String str) { 32 | View view = retrieveView(viewId); 33 | if (view instanceof TextView) { 34 | ((TextView) view).setText(str); 35 | } else if (view instanceof Button) { 36 | ((Button) view).setText(str); 37 | } 38 | } 39 | 40 | public void setImageByUrl(int viewId, String url) { 41 | View view = retrieveView(viewId); 42 | // if(view instanceof RatioImageView){ //普通图片用glide加载 43 | // Glide.with(EApplication.getInstance()).load(url) 44 | // .crossFade().into((RatioImageView)view); 45 | // }else if(view instanceof PLAImageView){ 46 | // Glide.with(EApplication.getInstance()).load(url) 47 | // .crossFade().into((PLAImageView) view); 48 | // }else if(view instanceof SquaredImageView){ 49 | // Glide.with(EApplication.getInstance()).load(url) 50 | // .crossFade().into((SquaredImageView) view); 51 | // }else 52 | if (view instanceof PLAImageView) { 53 | Glide.with(EApplication.getInstance()).load(url) 54 | .crossFade().into((PLAImageView) view); 55 | } else if (view instanceof ImageView) { 56 | Glide.with(EApplication.getInstance()).load(url) 57 | .crossFade().into((ImageView) view); 58 | } else if (view instanceof SimpleDraweeView) { 59 | Uri uri = Uri.parse(url); 60 | ((SimpleDraweeView) view).setImageURI(uri); 61 | } 62 | } 63 | 64 | public TextView getTextView(int viewId) { 65 | return retrieveView(viewId); 66 | } 67 | 68 | public Button getButton(int viewId) { 69 | return retrieveView(viewId); 70 | } 71 | 72 | public ImageView getImageView(int viewId) { 73 | return retrieveView(viewId); 74 | } 75 | 76 | public View getView(int viewId) { 77 | return retrieveView(viewId); 78 | } 79 | 80 | protected T retrieveView(int viewId) { 81 | View view = views.get(viewId); 82 | if (view == null) { 83 | view = itemView.findViewById(viewId); 84 | views.put(viewId, view); 85 | } 86 | return (T) view; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/adapter/BaseQuickAdapter.java: -------------------------------------------------------------------------------- 1 | package lico.example.adapter; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | 9 | import java.util.HashMap; 10 | import java.util.List; 11 | import java.util.Map; 12 | 13 | 14 | /** 15 | * Created by zwl on 2015/8/25. 16 | */ 17 | public abstract class BaseQuickAdapter extends RecyclerView.Adapter { 18 | protected static final String TAG = BaseQuickAdapter.class.getSimpleName(); 19 | 20 | protected final Context mContext; 21 | 22 | protected final int mLayoutResId; 23 | 24 | protected final List data; 25 | 26 | private Map> canClickItem; 27 | 28 | public BaseQuickAdapter(Context mContext, int mLayoutResId) { 29 | this(mContext, mLayoutResId, null); 30 | setHasStableIds(true); 31 | } 32 | 33 | public BaseQuickAdapter(Context mContext, int mLayoutResId, List data) { 34 | this.mContext = mContext; 35 | this.mLayoutResId = mLayoutResId; 36 | this.data = data; 37 | } 38 | 39 | @Override 40 | public BaseAdapterHelper onCreateViewHolder(ViewGroup parent, int viewType) { 41 | View view = LayoutInflater.from(parent.getContext()).inflate(mLayoutResId, parent, false); 42 | BaseAdapterHelper vh = new BaseAdapterHelper(view); 43 | return vh; 44 | } 45 | 46 | @Override 47 | public void onBindViewHolder(BaseAdapterHelper holder, int position) { 48 | if (holder != null) { 49 | addInternalClickListener(holder.itemView, position, data.get(position)); 50 | } 51 | holder.itemView.setTag(position); 52 | T item = getItem(position); 53 | convert((H) holder, item); 54 | } 55 | 56 | public List getDataList() { 57 | return data; 58 | } 59 | 60 | @Override 61 | public int getItemCount() { 62 | return data.size(); 63 | } 64 | 65 | public T getItem(int position) { 66 | if (position >= data.size()) 67 | return null; 68 | return data.get(position); 69 | } 70 | 71 | protected abstract void convert(H helper, T item); 72 | 73 | private void addInternalClickListener(final View itemV, final Integer position, final T valuesMap) { 74 | if (canClickItem != null) { 75 | for (Integer key : canClickItem.keySet()) { 76 | View inView = itemV.findViewById(key); 77 | final onInternalClickListener listener = canClickItem.get(key); 78 | if (inView != null && listener != null) { 79 | inView.setOnClickListener(new View.OnClickListener() { 80 | @Override 81 | public void onClick(View view) { 82 | listener.OnClickListener(itemV, view, position, valuesMap); 83 | } 84 | }); 85 | inView.setOnLongClickListener(new View.OnLongClickListener() { 86 | @Override 87 | public boolean onLongClick(View view) { 88 | listener.OnLongClickListener(itemV, view, position, 89 | valuesMap); 90 | return true; 91 | } 92 | }); 93 | } 94 | } 95 | } 96 | } 97 | 98 | public void setOnInViewClickListener(Integer key, onInternalClickListener onClickListener) { 99 | if (canClickItem == null) 100 | canClickItem = new HashMap>(); 101 | canClickItem.put(key, onClickListener); 102 | 103 | } 104 | 105 | public interface onInternalClickListener { 106 | void OnClickListener(View parentV, View v, Integer position, T values); 107 | 108 | void OnLongClickListener(View parentV, View v, Integer position, T values); 109 | } 110 | 111 | public static class onInternalClickListenerImpl implements onInternalClickListener { 112 | @Override 113 | public void OnClickListener(View parentV, View v, Integer position, T values) { 114 | 115 | } 116 | 117 | @Override 118 | public void OnLongClickListener(View parentV, View v, Integer position, T values) { 119 | 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/adapter/ContentPagerAdapter.java: -------------------------------------------------------------------------------- 1 | package lico.example.adapter; 2 | 3 | import android.support.v4.app.Fragment; 4 | import android.support.v4.app.FragmentManager; 5 | import android.support.v4.app.FragmentPagerAdapter; 6 | 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | import lico.example.fragment.ContentListFragment; 12 | 13 | /** 14 | * Created by zzk on 15/12/22. 15 | */ 16 | public class ContentPagerAdapter extends FragmentPagerAdapter { 17 | 18 | private List mFragmentTitles = new ArrayList<>(); 19 | private List tids = new ArrayList<>(); 20 | 21 | public ContentPagerAdapter(FragmentManager fm, List strings, List ids) { 22 | super(fm); 23 | this.mFragmentTitles = strings; 24 | this.tids = ids; 25 | } 26 | 27 | @Override 28 | public Fragment getItem(int position) { 29 | return ContentListFragment.newInstance(tids.get(position)); 30 | } 31 | 32 | @Override 33 | public int getCount() { 34 | return mFragmentTitles == null ? 0 : mFragmentTitles.size(); 35 | } 36 | 37 | @Override 38 | public CharSequence getPageTitle(int position) { 39 | return mFragmentTitles == null ? null : mFragmentTitles.get(position); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/adapter/SimpleRecyclerAdapter.java: -------------------------------------------------------------------------------- 1 | package lico.example.adapter; 2 | 3 | import android.content.Context; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Created by Administrator on 2015/8/25. 9 | */ 10 | public abstract class SimpleRecyclerAdapter extends BaseQuickAdapter { 11 | 12 | 13 | public SimpleRecyclerAdapter(Context mContext, List data, int mLayoutResId) { 14 | super(mContext, mLayoutResId, data); 15 | } 16 | 17 | 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/adapter/TabFragmentPagerAdapter.java: -------------------------------------------------------------------------------- 1 | package lico.example.adapter; 2 | 3 | import android.support.v4.app.Fragment; 4 | import android.support.v4.app.FragmentManager; 5 | import android.support.v4.app.FragmentPagerAdapter; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | import lico.example.fragment.ContentListFragment; 11 | import lico.example.fragment.ImageListFragment; 12 | 13 | /** 14 | * Created by zwl on 2015/8/31. 15 | */ 16 | public class TabFragmentPagerAdapter extends FragmentPagerAdapter { 17 | 18 | private List mFragmentTitles = new ArrayList<>(); 19 | private int mType; 20 | 21 | public TabFragmentPagerAdapter(FragmentManager fm, List strings, int type) { 22 | super(fm); 23 | this.mFragmentTitles = strings; 24 | mType = type; 25 | } 26 | 27 | @Override 28 | public Fragment getItem(int position) { 29 | if (mType == 1){ 30 | return ImageListFragment.newInstance(mFragmentTitles.get(position)); 31 | } else { 32 | return ContentListFragment.newInstance(mFragmentTitles.get(position)); 33 | } 34 | 35 | } 36 | 37 | @Override 38 | public int getCount() { 39 | return mFragmentTitles == null ? 0 : mFragmentTitles.size(); 40 | } 41 | 42 | @Override 43 | public CharSequence getPageTitle(int position) { 44 | return mFragmentTitles == null ? null : mFragmentTitles.get(position); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/app/EApplication.java: -------------------------------------------------------------------------------- 1 | package lico.example.app; 2 | 3 | import android.app.Application; 4 | 5 | import com.facebook.drawee.backends.pipeline.Fresco; 6 | import com.squareup.leakcanary.LeakCanary; 7 | 8 | 9 | /** 10 | * Created by zzk on 15/12/7. 11 | */ 12 | public class EApplication extends Application{ 13 | private static EApplication instance = null; 14 | @Override 15 | public void onCreate() { 16 | super.onCreate(); 17 | instance = this; 18 | Fresco.initialize(this) ; 19 | LeakCanary.install(this); 20 | } 21 | 22 | public static EApplication getInstance(){ 23 | if(instance == null){ 24 | synchronized (EApplication.class){ 25 | if(instance == null){ 26 | instance = new EApplication(); 27 | } 28 | } 29 | } 30 | return instance; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/bean/HttpResponseEntity.java: -------------------------------------------------------------------------------- 1 | package lico.example.bean; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by zwl on 15/7/27. 7 | */ 8 | public class HttpResponseEntity implements Serializable { 9 | public int responseCode; 10 | public String errorMsg; 11 | 12 | public HttpResponseEntity(int responseCode, String errorMsg) { 13 | this.responseCode = responseCode; 14 | this.errorMsg = errorMsg; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/bean/ImagesListEntity.java: -------------------------------------------------------------------------------- 1 | package lico.example.bean; 2 | 3 | import android.os.Parcel; 4 | import android.os.Parcelable; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * Created by zwl on 2015/9/23. 10 | */ 11 | public class ImagesListEntity implements Parcelable { 12 | 13 | public String id; 14 | public String desc; 15 | public List tags; 16 | public String fromPageTitle; 17 | public String column; 18 | public String date; 19 | public String downloadUrl; 20 | public String imageUrl; 21 | public int imageWidth; 22 | public int imageHeight; 23 | public String thumbnailUrl; 24 | public int thumbnailWidth; 25 | public int thumbnailHeight; 26 | public String thumbnailLargeUrl; 27 | public int thumbnailLargeWidth; 28 | public int thumbnailLargeHeight; 29 | public String thumbnailLargeTnUrl; 30 | public int thumbnailLargeTnWidth; 31 | public int thumbnailLargeTnHeight; 32 | public String siteName; 33 | public String siteLogo; 34 | public String siteUrl; 35 | public String fromUrl; 36 | public String objUrl; 37 | public String shareUrl; 38 | public String albumId; 39 | public int isAlbum; 40 | public String albumName; 41 | public int albumNum; 42 | public String title; 43 | 44 | 45 | @Override 46 | public int describeContents() { 47 | return 0; 48 | } 49 | 50 | @Override 51 | public void writeToParcel(Parcel dest, int flags) { 52 | dest.writeString(this.id); 53 | dest.writeString(this.desc); 54 | dest.writeStringList(this.tags); 55 | dest.writeString(this.fromPageTitle); 56 | dest.writeString(this.column); 57 | dest.writeString(this.date); 58 | dest.writeString(this.downloadUrl); 59 | dest.writeString(this.imageUrl); 60 | dest.writeInt(this.imageWidth); 61 | dest.writeInt(this.imageHeight); 62 | dest.writeString(this.thumbnailUrl); 63 | dest.writeInt(this.thumbnailWidth); 64 | dest.writeString(this.thumbnailLargeUrl); 65 | dest.writeInt(this.thumbnailHeight); 66 | dest.writeInt(this.thumbnailLargeWidth); 67 | dest.writeInt(this.thumbnailLargeHeight); 68 | dest.writeString(this.thumbnailLargeTnUrl); 69 | dest.writeInt(this.thumbnailLargeTnWidth); 70 | dest.writeInt(this.thumbnailLargeTnHeight); 71 | dest.writeString(this.siteName); 72 | dest.writeString(this.siteLogo); 73 | dest.writeString(this.siteUrl); 74 | dest.writeString(this.fromUrl); 75 | dest.writeString(this.objUrl); 76 | dest.writeString(this.shareUrl); 77 | dest.writeString(this.albumId); 78 | dest.writeInt(this.isAlbum); 79 | dest.writeString(this.albumName); 80 | dest.writeInt(this.albumNum); 81 | dest.writeString(this.title); 82 | } 83 | 84 | public ImagesListEntity() { 85 | } 86 | 87 | protected ImagesListEntity(Parcel in) { 88 | this.id = in.readString(); 89 | this.desc = in.readString(); 90 | this.tags = in.createStringArrayList(); 91 | this.fromPageTitle = in.readString(); 92 | this.column = in.readString(); 93 | this.date = in.readString(); 94 | this.downloadUrl = in.readString(); 95 | this.imageUrl = in.readString(); 96 | this.imageWidth = in.readInt(); 97 | this.imageHeight = in.readInt(); 98 | this.thumbnailUrl = in.readString(); 99 | this.thumbnailWidth = in.readInt(); 100 | this.thumbnailLargeUrl = in.readString(); 101 | this.thumbnailHeight = in.readInt(); 102 | this.thumbnailLargeWidth = in.readInt(); 103 | this.thumbnailLargeHeight = in.readInt(); 104 | this.thumbnailLargeTnUrl = in.readString(); 105 | this.thumbnailLargeTnWidth = in.readInt(); 106 | this.thumbnailLargeTnHeight = in.readInt(); 107 | this.siteName = in.readString(); 108 | this.siteLogo = in.readString(); 109 | this.siteUrl = in.readString(); 110 | this.fromUrl = in.readString(); 111 | this.objUrl = in.readString(); 112 | this.shareUrl = in.readString(); 113 | this.albumId = in.readString(); 114 | this.isAlbum = in.readInt(); 115 | this.albumName = in.readString(); 116 | this.albumNum = in.readInt(); 117 | this.title = in.readString(); 118 | } 119 | 120 | public static final Creator CREATOR = new Creator() { 121 | public ImagesListEntity createFromParcel(Parcel source) { 122 | return new ImagesListEntity(source); 123 | } 124 | 125 | public ImagesListEntity[] newArray(int size) { 126 | return new ImagesListEntity[size]; 127 | } 128 | }; 129 | } 130 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/bean/JcodeInfo.java: -------------------------------------------------------------------------------- 1 | package lico.example.bean; 2 | 3 | import android.os.Parcel; 4 | import android.os.Parcelable; 5 | 6 | /** 7 | * Created by zzk on 15/12/30. 8 | * 泡在网上的日子 数据实体类 http://www.jcodecraeer.com/ 9 | */ 10 | public class JcodeInfo implements Parcelable{ 11 | 12 | public String detailUrl; 13 | public String imageUrl; 14 | public String title; 15 | 16 | 17 | @Override 18 | public int describeContents() { 19 | return 0; 20 | } 21 | 22 | @Override 23 | public void writeToParcel(Parcel dest, int flags) { 24 | dest.writeString(this.detailUrl); 25 | dest.writeString(this.imageUrl); 26 | dest.writeString(this.title); 27 | } 28 | 29 | public JcodeInfo() { 30 | } 31 | 32 | protected JcodeInfo(Parcel in) { 33 | this.detailUrl = in.readString(); 34 | this.imageUrl = in.readString(); 35 | this.title = in.readString(); 36 | } 37 | 38 | public static final Creator CREATOR = new Creator() { 39 | public JcodeInfo createFromParcel(Parcel source) { 40 | return new JcodeInfo(source); 41 | } 42 | 43 | public JcodeInfo[] newArray(int size) { 44 | return new JcodeInfo[size]; 45 | } 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/bean/ResponseImagesListEntity.java: -------------------------------------------------------------------------------- 1 | package lico.example.bean; 2 | 3 | import android.os.Parcel; 4 | import android.os.Parcelable; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * Created by zwl on 2015/9/23. 10 | */ 11 | public class ResponseImagesListEntity implements Parcelable { 12 | 13 | public String col; 14 | public String tag; 15 | public String tag3; 16 | public String sort; 17 | public int totalNum; 18 | public int startIndex; 19 | public int returnNumber; 20 | public List imgs; 21 | 22 | 23 | @Override 24 | public int describeContents() { 25 | return 0; 26 | } 27 | 28 | @Override 29 | public void writeToParcel(Parcel dest, int flags) { 30 | dest.writeString(this.col); 31 | dest.writeString(this.tag); 32 | dest.writeString(this.tag3); 33 | dest.writeString(this.sort); 34 | dest.writeInt(this.totalNum); 35 | dest.writeInt(this.startIndex); 36 | dest.writeInt(this.returnNumber); 37 | dest.writeTypedList(imgs); 38 | } 39 | 40 | public ResponseImagesListEntity() { 41 | } 42 | 43 | protected ResponseImagesListEntity(Parcel in) { 44 | this.col = in.readString(); 45 | this.tag = in.readString(); 46 | this.tag3 = in.readString(); 47 | this.sort = in.readString(); 48 | this.totalNum = in.readInt(); 49 | this.startIndex = in.readInt(); 50 | this.returnNumber = in.readInt(); 51 | this.imgs = in.createTypedArrayList(ImagesListEntity.CREATOR); 52 | } 53 | 54 | public static final Creator CREATOR = new Creator() { 55 | public ResponseImagesListEntity createFromParcel(Parcel source) { 56 | return new ResponseImagesListEntity(source); 57 | } 58 | 59 | public ResponseImagesListEntity[] newArray(int size) { 60 | return new ResponseImagesListEntity[size]; 61 | } 62 | }; 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/fragment/ContentFragment.java: -------------------------------------------------------------------------------- 1 | package lico.example.fragment; 2 | 3 | import android.content.Context; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | import lico.example.R; 9 | import lico.example.presenter.FragmentPresenter; 10 | import lico.example.view.ContentView; 11 | import rx.Observable; 12 | import rx.Subscriber; 13 | import rx.android.schedulers.AndroidSchedulers; 14 | import rx.functions.Func1; 15 | 16 | /** 17 | * Created by zzk on 15/12/22. 18 | */ 19 | public class ContentFragment extends FragmentPresenter { 20 | 21 | private String[] ids = new String[]{"6", "18", "5", "27", "14"}; 22 | 23 | @Override 24 | protected void initData() { 25 | super.initData(); 26 | getTitle(getActivity()); 27 | } 28 | 29 | private void getTitle(Context context) { 30 | Observable.just(1) 31 | .map(new Func1>() { 32 | 33 | @Override 34 | public List call(Integer integer) { 35 | return getList(); 36 | } 37 | }) 38 | .observeOn(AndroidSchedulers.mainThread()) 39 | .subscribe(new Subscriber>() { 40 | @Override 41 | public void onCompleted() { 42 | 43 | } 44 | 45 | @Override 46 | public void onError(Throwable e) { 47 | 48 | } 49 | 50 | @Override 51 | public void onNext(List list) { 52 | mView.initViewPager(list.get(0), list.get(1), getChildFragmentManager()); 53 | } 54 | }); 55 | } 56 | 57 | private List getList() { 58 | List list = new ArrayList<>(); 59 | list.add(getResources().getStringArray(R.array.archive_list)); 60 | list.add(ids); 61 | 62 | return list; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/fragment/ContentListFragment.java: -------------------------------------------------------------------------------- 1 | package lico.example.fragment; 2 | 3 | import android.os.Bundle; 4 | import android.util.Log; 5 | 6 | import java.util.List; 7 | 8 | import lico.example.bean.JcodeInfo; 9 | import lico.example.presenter.FragmentPresenter; 10 | import lico.example.utils.DataUtil; 11 | import lico.example.view.ContentListView; 12 | import lico.example.views.PullLoadMoreRecyclerView; 13 | 14 | import rx.Observable; 15 | import rx.Subscriber; 16 | import rx.android.schedulers.AndroidSchedulers; 17 | import rx.functions.Func1; 18 | import rx.schedulers.Schedulers; 19 | 20 | /** 21 | * Created by zzk on 15/12/22. 22 | */ 23 | public class ContentListFragment extends FragmentPresenter implements PullLoadMoreRecyclerView.PullLoadMoreListener { 24 | 25 | String tid; 26 | boolean isRefresh = true; 27 | int page = 1; 28 | 29 | public static ContentListFragment newInstance(String id) { 30 | ContentListFragment contentListFragment = new ContentListFragment(); 31 | Bundle bundle = new Bundle(); 32 | bundle.putString("tid", id); 33 | contentListFragment.setArguments(bundle); 34 | return contentListFragment; 35 | } 36 | 37 | @Override 38 | protected void lazyData() { 39 | super.lazyData(); 40 | 41 | mView.initViews(getActivity(), this); 42 | getData(); 43 | } 44 | 45 | private void getData() { 46 | tid = getArguments().getString("tid"); 47 | Observable.just("") 48 | .map(new Func1>() { 49 | @Override 50 | public List call(String s) { 51 | return DataUtil.getJcodeData(tid, page); 52 | } 53 | }) 54 | .observeOn(AndroidSchedulers.mainThread()) 55 | .subscribeOn(Schedulers.newThread()) 56 | .subscribe(new Subscriber>() { 57 | @Override 58 | public void onCompleted() { 59 | } 60 | 61 | @Override 62 | public void onError(Throwable e) { 63 | } 64 | 65 | @Override 66 | public void onNext(List jcodeInfos) { 67 | Log.e("x", "xx : " + jcodeInfos.size()); 68 | if (isRefresh) mView.refreshListData(jcodeInfos); 69 | else mView.addListData(jcodeInfos); 70 | } 71 | }); 72 | } 73 | 74 | @Override 75 | public void onRefresh() { 76 | isRefresh = true; 77 | page = 1; 78 | getData(); 79 | } 80 | 81 | @Override 82 | public void onLoadMore() { 83 | isRefresh = false; 84 | page++; 85 | getData(); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/fragment/ImageFragment.java: -------------------------------------------------------------------------------- 1 | package lico.example.fragment; 2 | 3 | import android.content.Context; 4 | 5 | import lico.example.R; 6 | import lico.example.presenter.FragmentPresenter; 7 | import lico.example.view.ImagesView; 8 | import rx.Observable; 9 | import rx.Subscriber; 10 | import rx.android.schedulers.AndroidSchedulers; 11 | import rx.functions.Func1; 12 | 13 | /** 14 | * Created by zzk on 15/11/28. 15 | */ 16 | public class ImageFragment extends FragmentPresenter{ 17 | 18 | 19 | @Override 20 | protected void initData() { //不是懒加载 21 | super.initData(); 22 | getTitles(getActivity()); 23 | } 24 | 25 | private void getTitles(Context context){ 26 | 27 | Observable.just(R.array.images_category_list) 28 | .map(new Func1() { 29 | 30 | @Override 31 | public String[] call(Integer integer) { 32 | return context.getResources().getStringArray(R.array.images_category_list); 33 | } 34 | }) 35 | .observeOn(AndroidSchedulers.mainThread()) 36 | .subscribe(new Subscriber() { 37 | @Override 38 | public void onCompleted() { 39 | 40 | } 41 | 42 | @Override 43 | public void onError(Throwable e) { 44 | 45 | } 46 | 47 | @Override 48 | public void onNext(String[] strings) { 49 | mView.initViewPager(strings, getFragmentManager()); 50 | } 51 | }); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/fragment/ImageListFragment.java: -------------------------------------------------------------------------------- 1 | package lico.example.fragment; 2 | 3 | import android.os.Bundle; 4 | 5 | import com.jcodecraeer.xrecyclerview.XRecyclerView; 6 | 7 | 8 | import lico.example.bean.ResponseImagesListEntity; 9 | import lico.example.listener.HttpApi; 10 | import lico.example.presenter.FragmentPresenter; 11 | import lico.example.view.ImageListView; 12 | import retrofit.GsonConverterFactory; 13 | import retrofit.Retrofit; 14 | import retrofit.RxJavaCallAdapterFactory; 15 | import rx.Subscriber; 16 | import rx.android.schedulers.AndroidSchedulers; 17 | import rx.schedulers.Schedulers; 18 | 19 | /** 20 | * Created by zzk on 15/12/7. 21 | */ 22 | public class ImageListFragment extends FragmentPresenter implements XRecyclerView.LoadingListener{ 23 | 24 | boolean isRefresh = true; 25 | String keyword; 26 | int page = 0; 27 | 28 | public static ImageListFragment newInstance(String title) { 29 | ImageListFragment imageListFragment = new ImageListFragment(); 30 | Bundle bundle = new Bundle(); 31 | bundle.putString("keyword", title); 32 | imageListFragment.setArguments(bundle); 33 | return imageListFragment; 34 | } 35 | 36 | @Override 37 | protected void lazyData() { 38 | super.lazyData(); 39 | mView.initViews(getActivity(), this); 40 | getData(); 41 | } 42 | 43 | private void getData() { 44 | keyword = getArguments().getString("keyword"); 45 | Retrofit retrofit = new Retrofit.Builder() 46 | .baseUrl("http://image.baidu.com") 47 | .addConverterFactory(GsonConverterFactory.create()) 48 | .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 49 | .build(); 50 | HttpApi api = retrofit.create(HttpApi.class); 51 | api.getImagess(keyword, "全部", page*10, 10, 1) 52 | .observeOn(AndroidSchedulers.mainThread()) 53 | .subscribeOn(Schedulers.newThread()) 54 | .subscribe(new Subscriber() { 55 | @Override 56 | public void onCompleted() {} 57 | 58 | @Override 59 | public void onError(Throwable e) {} 60 | 61 | @Override 62 | public void onNext(ResponseImagesListEntity entity) { 63 | if(isRefresh) mView.refreshListData(entity.imgs); 64 | mView.addListData(entity.imgs); 65 | } 66 | }); 67 | 68 | } 69 | 70 | @Override 71 | public void onRefresh() { 72 | isRefresh = true; 73 | page = 0; 74 | getData(); 75 | } 76 | 77 | @Override 78 | public void onLoadMore() { 79 | isRefresh = false; 80 | page++; 81 | getData(); 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/fragment/LazyFragment.java: -------------------------------------------------------------------------------- 1 | package lico.example.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 | /** 11 | * Created by zzk on 15/11/26. 12 | */ 13 | public abstract class LazyFragment extends Fragment{ 14 | 15 | private boolean isVisible; 16 | 17 | private boolean isPrepared; 18 | 19 | private boolean isFirstLoad = true; 20 | 21 | @Nullable 22 | @Override 23 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 24 | isFirstLoad = true; 25 | View view = initViews(inflater, container, savedInstanceState); 26 | isPrepared = true; 27 | lazyLoad(); 28 | return view; 29 | } 30 | 31 | @Override 32 | public void setUserVisibleHint(boolean isVisibleToUser) { 33 | super.setUserVisibleHint(isVisibleToUser); 34 | if(getUserVisibleHint()){ 35 | isVisible = true; 36 | onVisible(); 37 | } else { 38 | isVisible = false; 39 | onInvisible(); 40 | } 41 | } 42 | 43 | @Override 44 | public void onHiddenChanged(boolean hidden) { 45 | super.onHiddenChanged(hidden); 46 | if(!hidden){ 47 | isVisible = true; 48 | onVisible(); 49 | } else { 50 | isVisible = false; 51 | onInvisible(); 52 | } 53 | } 54 | 55 | protected void onVisible(){ 56 | lazyLoad(); 57 | } 58 | 59 | protected void onInvisible(){ 60 | 61 | } 62 | 63 | protected void lazyLoad(){ 64 | if(!isPrepared || !isVisible || !isFirstLoad){ 65 | return; 66 | } 67 | isFirstLoad = false; 68 | initializeData(); 69 | } 70 | 71 | protected abstract View initViews(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState); 72 | 73 | protected abstract void initializeData(); 74 | 75 | 76 | } 77 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/helper/EventHelper.java: -------------------------------------------------------------------------------- 1 | package lico.example.helper; 2 | 3 | import android.support.design.widget.NavigationView; 4 | import android.view.View; 5 | 6 | import lico.example.presenter.IPresenter; 7 | 8 | /** 9 | * Created by zzk on 15/11/27. 10 | */ 11 | public class EventHelper { 12 | 13 | public static void click(IPresenter presenter, View ...views){ 14 | if(!(presenter instanceof View.OnClickListener)) return; 15 | if(views == null || views.length == 0) return; 16 | for (View v : views) v.setOnClickListener((View.OnClickListener) presenter); 17 | } 18 | 19 | public static void setNavigationItemSelected(IPresenter presenter, View ...views){ 20 | if(!(presenter instanceof NavigationView.OnNavigationItemSelectedListener)) return; 21 | if(views == null || views.length == 0) return; 22 | for (View v : views) ((NavigationView)v).setNavigationItemSelectedListener((NavigationView.OnNavigationItemSelectedListener) presenter); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/helper/GenericHelper.java: -------------------------------------------------------------------------------- 1 | package lico.example.helper; 2 | 3 | import java.lang.reflect.ParameterizedType; 4 | import java.lang.reflect.Type; 5 | 6 | /** 7 | * Created by zzk on 15/11/27. 8 | */ 9 | public class GenericHelper { 10 | 11 | public static Class getViewClass(Class klass){ 12 | Type type = klass.getGenericSuperclass(); 13 | if(type == null || !(type instanceof ParameterizedType)) return null; 14 | ParameterizedType parameterizedType = (ParameterizedType) type; 15 | Type[] types = parameterizedType.getActualTypeArguments(); 16 | if(types == null || types.length == 0) return null; 17 | return (Class) types[0]; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/listener/HttpApi.java: -------------------------------------------------------------------------------- 1 | package lico.example.listener; 2 | 3 | import lico.example.bean.ResponseImagesListEntity; 4 | import retrofit.http.GET; 5 | import retrofit.http.Query; 6 | import rx.Observable; 7 | 8 | 9 | /** 10 | * Created by zzk on 15/12/7. 11 | */ 12 | public interface HttpApi { 13 | 14 | @GET("/data/imgs") 15 | Observable getImagess(@Query("col") String col,@Query("tag")String tag, @Query("pn") int pn, @Query("rn") int rn, @Query("from") int from); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/listener/JSONParserCompleteListener.java: -------------------------------------------------------------------------------- 1 | package lico.example.listener; 2 | 3 | 4 | import lico.example.bean.HttpResponseEntity; 5 | 6 | /** 7 | * Created by zwl on 15/7/27. 8 | */ 9 | public interface JSONParserCompleteListener { 10 | public void ParserCompleteListener(HttpResponseEntity response, Object object); 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/presenter/ActivityPresenter.java: -------------------------------------------------------------------------------- 1 | package lico.example.presenter; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.support.v7.widget.Toolbar; 6 | import android.view.Menu; 7 | 8 | import lico.example.helper.GenericHelper; 9 | import lico.example.view.IView; 10 | 11 | /** 12 | * Created by zzk on 15/11/26. 13 | */ 14 | public class ActivityPresenter extends AppCompatActivity implements IPresenter { 15 | 16 | protected T mView; 17 | 18 | @Override 19 | protected void onCreate(Bundle savedInstanceState) { 20 | super.onCreate(savedInstanceState); 21 | try { 22 | mView = getViewClass().newInstance(); 23 | mView.create(getLayoutInflater(), null); 24 | mView.bindPresenter(this); 25 | setContentView(mView.getRootView()); 26 | initToolbar(); 27 | mView.bindEvent(); 28 | initData(); 29 | } catch (InstantiationException e) { 30 | e.printStackTrace(); 31 | } catch (IllegalAccessException e) { 32 | e.printStackTrace(); 33 | } 34 | } 35 | 36 | protected void initToolbar() { 37 | Toolbar toolbar = mView.getToolbar(); 38 | if (null != toolbar) { 39 | setSupportActionBar(toolbar); 40 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 41 | } 42 | } 43 | 44 | @Override 45 | public boolean onCreateOptionsMenu(Menu menu) { 46 | if (mView.getOptionsMenuId() != 0) { 47 | getMenuInflater().inflate(mView.getOptionsMenuId(), menu); 48 | } 49 | return super.onCreateOptionsMenu(menu); 50 | } 51 | 52 | @Override 53 | protected void onDestroy() { 54 | mView.destroy(); 55 | super.onDestroy(); 56 | } 57 | 58 | protected void initData(){} 59 | 60 | @Override 61 | public Class getViewClass() { 62 | return GenericHelper.getViewClass(getClass()); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/presenter/FragmentPresenter.java: -------------------------------------------------------------------------------- 1 | package lico.example.presenter; 2 | 3 | import android.os.Bundle; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | 8 | import lico.example.fragment.LazyFragment; 9 | import lico.example.helper.GenericHelper; 10 | import lico.example.view.IView; 11 | 12 | /** 13 | * Created by zzk on 15/11/26. 14 | */ 15 | public class FragmentPresenter extends LazyFragment implements IPresenter{ 16 | 17 | protected T mView; 18 | 19 | @Override 20 | protected View initViews(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 21 | View view = null; 22 | try{ 23 | mView = getViewClass().newInstance(); 24 | mView.create(inflater, container); 25 | mView.bindPresenter(this); 26 | view = mView.getRootView(); 27 | initData(); 28 | }catch (Exception e){ 29 | e.printStackTrace(); 30 | } 31 | return view; 32 | } 33 | 34 | 35 | 36 | @Override 37 | protected void initializeData() {//懒加载在这里,so在写个方法让子类去实现 38 | lazyData(); 39 | } 40 | 41 | @Override 42 | public void onDestroyView() { 43 | onDestroyV(); 44 | mView = null; 45 | super.onDestroyView(); 46 | } 47 | 48 | protected void onDestroyV() { 49 | } 50 | 51 | protected void initData(){} 52 | 53 | protected void lazyData(){} 54 | 55 | @Override 56 | public Class getViewClass() { 57 | return GenericHelper.getViewClass(getClass()); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/presenter/IPresenter.java: -------------------------------------------------------------------------------- 1 | package lico.example.presenter; 2 | 3 | /** 4 | * Created by zzk on 15/11/27. 5 | */ 6 | public interface IPresenter { 7 | Class getViewClass(); 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/ui/MainActivity.java: -------------------------------------------------------------------------------- 1 | package lico.example.ui; 2 | 3 | import android.content.Intent; 4 | import android.graphics.Bitmap; 5 | import android.view.View; 6 | import android.support.design.widget.NavigationView; 7 | import android.view.MenuItem; 8 | 9 | import lico.example.R; 10 | import lico.example.presenter.ActivityPresenter; 11 | import lico.example.utils.BitmapUtil; 12 | import lico.example.view.MainView; 13 | import rx.Observable; 14 | import rx.Subscriber; 15 | import rx.android.schedulers.AndroidSchedulers; 16 | import rx.functions.Func1; 17 | 18 | public class MainActivity extends ActivityPresenter 19 | implements NavigationView.OnNavigationItemSelectedListener, View.OnClickListener { 20 | 21 | @Override 22 | protected void initData() { 23 | super.initData(); 24 | getBitmap(); 25 | mView.setNavigationItemSelected(getSupportFragmentManager(), R.id.nav_camera); 26 | } 27 | 28 | @Override 29 | public boolean onOptionsItemSelected(MenuItem item) { 30 | return mView.setOptionsItemSelected(item.getItemId()); 31 | } 32 | 33 | @SuppressWarnings("StatementWithEmptyBody") 34 | @Override 35 | public boolean onNavigationItemSelected(MenuItem item) { 36 | return mView.setNavigationItemSelected(getSupportFragmentManager(), item.getItemId()); 37 | } 38 | 39 | @Override 40 | public void onClick(View v) { 41 | switch (v.getId()) { 42 | case R.id.fab: 43 | mView.setFabClick("我的天呐"); 44 | break; 45 | case R.id.imageView: 46 | Intent intent = new Intent(this, PersonalActivity.class); 47 | startActivity(intent); 48 | break; 49 | } 50 | } 51 | 52 | @Override 53 | public void onBackPressed() { 54 | if (mView.closeDrawer()) 55 | return; 56 | super.onBackPressed(); 57 | } 58 | 59 | private void getBitmap() { 60 | Observable.just(R.mipmap.avator) 61 | .map(new Func1() { 62 | @Override 63 | public Bitmap call(Integer integer) { 64 | return BitmapUtil.matrixBitmap(MainActivity.this, integer); 65 | } 66 | }) 67 | .map(new Func1() { 68 | @Override 69 | public Bitmap call(Bitmap bitmap) { 70 | return BitmapUtil.blurBitmap(MainActivity.this, bitmap, 15.5f); 71 | } 72 | }) 73 | .observeOn(AndroidSchedulers.mainThread()) 74 | .subscribe(new Subscriber() { 75 | @Override 76 | public void onCompleted() { 77 | } 78 | 79 | @Override 80 | public void onError(Throwable e) { 81 | } 82 | 83 | @Override 84 | public void onNext(Bitmap bitmap) { 85 | mView.setAvator(bitmap); 86 | } 87 | }); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/ui/PersonalActivity.java: -------------------------------------------------------------------------------- 1 | package lico.example.ui; 2 | 3 | import android.view.MenuItem; 4 | 5 | import lico.example.presenter.ActivityPresenter; 6 | import lico.example.view.PersonalView; 7 | 8 | /** 9 | * Created by zzk on 15/11/28. 10 | */ 11 | public class PersonalActivity extends ActivityPresenter{ 12 | 13 | @Override 14 | public boolean onOptionsItemSelected(MenuItem item) { 15 | int id = item.getItemId(); 16 | switch (id){ 17 | case android.R.id.home: 18 | finish(); 19 | return true; 20 | default: 21 | return super.onOptionsItemSelected(item); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/ui/SpaceImageDetailActivity.java: -------------------------------------------------------------------------------- 1 | package lico.example.ui; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.ImageView; 8 | 9 | import com.bumptech.glide.Glide; 10 | 11 | import lico.example.views.SmoothImageView; 12 | 13 | 14 | /** 15 | * Created by zwl on 2015/8/20. 16 | * 单张图片点击详情activity 17 | */ 18 | public class SpaceImageDetailActivity extends Activity { 19 | private String imgUrl; 20 | private int mPosition; 21 | private int mLocationX; 22 | private int mLocationY; 23 | private int mWidth; 24 | private int mHeight; 25 | SmoothImageView imageView = null; 26 | 27 | @Override 28 | protected void onCreate(Bundle savedInstanceState) { 29 | super.onCreate(savedInstanceState); 30 | imgUrl = (String) getIntent().getSerializableExtra("images"); 31 | mLocationX = getIntent().getIntExtra("locationX", 0); 32 | mLocationY = getIntent().getIntExtra("locationY", 0); 33 | mWidth = getIntent().getIntExtra("width", 0); 34 | mHeight = getIntent().getIntExtra("height", 0); 35 | 36 | imageView = new SmoothImageView(this); 37 | imageView.setOriginalInfo(mWidth, mHeight, mLocationX, mLocationY); 38 | imageView.transformIn(); 39 | imageView.setLayoutParams(new ViewGroup.LayoutParams(-1, -1)); 40 | imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); 41 | setContentView(imageView); 42 | Glide.with(this).load(imgUrl) 43 | .crossFade().into((SmoothImageView) imageView); 44 | // ScaleAnimation scaleAnimation = new ScaleAnimation(0.5f, 1.0f, 0.5f, 45 | // 1.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 46 | // 0.5f); 47 | // scaleAnimation.setDuration(300); 48 | // scaleAnimation.setInterpolator(new AccelerateInterpolator()); 49 | // imageView.startAnimation(scaleAnimation); 50 | imageView.setOnClickListener(new View.OnClickListener() { 51 | @Override 52 | public void onClick(View v) { 53 | outExit(); 54 | } 55 | }); 56 | } 57 | 58 | @Override 59 | public void onBackPressed() { 60 | outExit(); 61 | } 62 | 63 | private void outExit(){ 64 | imageView.setOnTransformListener(new SmoothImageView.TransformListener() { 65 | @Override 66 | public void onTransformComplete(int mode) { 67 | if (mode == 2) { 68 | finish(); 69 | } 70 | } 71 | }); 72 | imageView.transformOut(); 73 | } 74 | 75 | @Override 76 | protected void onPause() { 77 | super.onPause(); 78 | if (isFinishing()) { 79 | overridePendingTransition(0, 0); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/utils/BitmapUtil.java: -------------------------------------------------------------------------------- 1 | package lico.example.utils; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.Canvas; 6 | import android.graphics.ColorMatrix; 7 | import android.graphics.ColorMatrixColorFilter; 8 | import android.graphics.Paint; 9 | import android.graphics.drawable.BitmapDrawable; 10 | import android.graphics.drawable.Drawable; 11 | import android.renderscript.Allocation; 12 | import android.renderscript.Element; 13 | import android.renderscript.RenderScript; 14 | import android.renderscript.ScriptIntrinsicBlur; 15 | 16 | import lico.example.R; 17 | 18 | /** 19 | * Created by zzk on 15/11/28. 20 | */ 21 | public class BitmapUtil { 22 | 23 | /** 24 | * 图片模糊效果 25 | */ 26 | public static Bitmap blurBitmap(Context context, Bitmap bitmap, float radius){ 27 | Bitmap outBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); 28 | RenderScript rs = RenderScript.create(context); 29 | 30 | ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); 31 | 32 | Allocation allIn = Allocation.createFromBitmap(rs, bitmap); 33 | Allocation allOut = Allocation.createFromBitmap(rs, bitmap); 34 | 35 | blurScript.setRadius(radius); 36 | 37 | blurScript.setInput(allIn); 38 | blurScript.forEach(allOut); 39 | 40 | allOut.copyTo(outBitmap); 41 | 42 | bitmap.recycle(); 43 | rs.destroy(); 44 | 45 | return outBitmap; 46 | } 47 | 48 | /** 49 | * 图片黑白效果 50 | */ 51 | public static Bitmap matrixBitmap(Context context, int drawableId){ 52 | Drawable drawable = context.getResources().getDrawable(R.mipmap.avator); 53 | Bitmap srcBitmap = BitmapUtil.drawableToBitmap(drawable); 54 | float[] src = new float[]{ 55 | 0.28F, 0.60F, 0.40F, 0, 0, 56 | 0.28F, 0.60F, 0.40F, 0, 0, 57 | 0.28F, 0.60F, 0.40F, 0, 0, 58 | 0, 0, 0, 1, 0, 59 | }; 60 | ColorMatrix cm = new ColorMatrix(src); 61 | ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm); 62 | Bitmap resultBitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), 63 | Bitmap.Config.ARGB_8888); 64 | Canvas canvas = new Canvas(resultBitmap ); 65 | Paint paint = new Paint(); 66 | paint.setAntiAlias(true); 67 | paint.setAlpha(100); 68 | paint.setColorFilter(f); 69 | canvas.drawBitmap(srcBitmap, 0, 0, paint); 70 | return resultBitmap; 71 | } 72 | 73 | /** 74 | * drawable转bitmap 75 | */ 76 | public static Bitmap drawableToBitmap(Drawable drawable){ 77 | Bitmap bitmap = ((BitmapDrawable)drawable).getBitmap(); 78 | return bitmap; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/utils/DataUtil.java: -------------------------------------------------------------------------------- 1 | package lico.example.utils; 2 | 3 | 4 | import org.jsoup.Jsoup; 5 | import org.jsoup.nodes.Document; 6 | import org.jsoup.nodes.Element; 7 | import org.jsoup.select.Elements; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | import lico.example.bean.JcodeInfo; 13 | 14 | /** 15 | * Created by zzk on 15/12/31. 16 | */ 17 | public class DataUtil { 18 | 19 | public static List getJcodeData(String tid, int page) { 20 | List mList = new ArrayList<>(); 21 | try { 22 | String url = "http://www.jcodecraeer.com/plus/list.php?tid=" + tid + "&TotalResult=1415&PageNo=" + page; 23 | Document doc = Jsoup.connect(url).get(); 24 | Elements links = doc.select("div.archive-list-item"); 25 | for (Element e : links) { 26 | JcodeInfo info = new JcodeInfo(); 27 | info.detailUrl = e.select("a").attr("href"); 28 | info.imageUrl = "http://www.jcodecraeer.com"+e.select("img").attr("src"); 29 | info.title = e.select("div.post-intro").select("a[href]").attr("title"); 30 | mList.add(info); 31 | } 32 | return mList; 33 | } catch (Exception e) { 34 | e.printStackTrace(); 35 | } 36 | return null; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/view/ContentView.java: -------------------------------------------------------------------------------- 1 | package lico.example.view; 2 | 3 | import android.support.design.widget.TabLayout; 4 | import android.support.v4.app.FragmentManager; 5 | import android.support.v4.view.ViewPager; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | import butterknife.Bind; 11 | import lico.example.R; 12 | import lico.example.adapter.ContentPagerAdapter; 13 | 14 | /** 15 | * Created by zzk on 15/12/22. 16 | */ 17 | public class ContentView extends ViewImpl { 18 | @Bind(R.id.content_tab) 19 | TabLayout tabs; 20 | @Bind(R.id.content_viewpager) 21 | ViewPager viewpager; 22 | 23 | private ContentPagerAdapter mPagerAdapter; 24 | 25 | @Override 26 | public int getLayoutId() { 27 | return R.layout.fragment_content; 28 | } 29 | 30 | public void initViewPager(String[] titles, String[] ids, FragmentManager fragmentManager) { 31 | viewpager.setOffscreenPageLimit(titles.length + 1); 32 | List tids = new ArrayList<>(); 33 | List title = new ArrayList<>(); 34 | for (String titles1 : titles) { 35 | title.add(titles1); 36 | } 37 | for (String id : ids) { 38 | tids.add(id); 39 | } 40 | mPagerAdapter = new ContentPagerAdapter(fragmentManager, title, tids); 41 | viewpager.setAdapter(mPagerAdapter); 42 | tabs.setupWithViewPager(viewpager); 43 | tabs.setTabsFromPagerAdapter(mPagerAdapter); 44 | } 45 | 46 | @Override 47 | public void destroy() { 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/view/ContentlistView.java: -------------------------------------------------------------------------------- 1 | package lico.example.view; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | import butterknife.Bind; 10 | import lico.example.R; 11 | import lico.example.adapter.BaseAdapterHelper; 12 | import lico.example.adapter.SimpleRecyclerAdapter; 13 | import lico.example.bean.JcodeInfo; 14 | import lico.example.views.PullLoadMoreRecyclerView; 15 | 16 | /** 17 | * Created by zzk on 15/12/22. 18 | */ 19 | public class ContentListView extends ViewImpl { 20 | 21 | @Bind(R.id.pullloadmoreview) 22 | PullLoadMoreRecyclerView pullloadmoreview; 23 | 24 | private List mList = new ArrayList<>(); 25 | private SimpleRecyclerAdapter mAdapter; 26 | 27 | @Override 28 | public int getLayoutId() { 29 | return R.layout.fragment_content_list; 30 | } 31 | 32 | public void initViews(Context context, PullLoadMoreRecyclerView.PullLoadMoreListener listener) { 33 | pullloadmoreview.setRefreshing(true); 34 | pullloadmoreview.setLinearLayout(); 35 | pullloadmoreview.setOnPullLoadMoreListener(listener); 36 | 37 | 38 | mAdapter = new SimpleRecyclerAdapter(context, mList, R.layout.view_content_list) { 39 | 40 | @Override 41 | protected void convert(BaseAdapterHelper helper, JcodeInfo item) { 42 | helper.setText(R.id.content_text, item.title); 43 | helper.setImageByUrl(R.id.user_avator, item.imageUrl); 44 | } 45 | }; 46 | pullloadmoreview.setAdapter(mAdapter); 47 | } 48 | 49 | public void refreshListData(List list) { 50 | mAdapter.getDataList().clear(); 51 | mAdapter.getDataList().addAll(list); 52 | mAdapter.notifyDataSetChanged(); 53 | pullloadmoreview.setPullLoadMoreCompleted(); 54 | Log.e("x", "x getDataList : " + mAdapter.getDataList().size()); 55 | } 56 | 57 | public void addListData(List list) { 58 | mAdapter.getDataList().addAll(list); 59 | mAdapter.notifyDataSetChanged(); 60 | pullloadmoreview.setPullLoadMoreCompleted(); 61 | } 62 | 63 | @Override 64 | public void destroy() { 65 | 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/view/IView.java: -------------------------------------------------------------------------------- 1 | package lico.example.view; 2 | 3 | import android.os.Bundle; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.support.v7.widget.Toolbar; 8 | 9 | import lico.example.presenter.IPresenter; 10 | 11 | /** 12 | * Created by zzk on 15/11/26. 13 | */ 14 | public interface IView { 15 | 16 | void create(LayoutInflater inflater, ViewGroup container); 17 | 18 | View getRootView(); 19 | 20 | int getOptionsMenuId(); 21 | 22 | Toolbar getToolbar(); 23 | 24 | void bindPresenter(IPresenter presenter); 25 | 26 | void bindEvent(); 27 | 28 | void destroy(); 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/view/ImageListView.java: -------------------------------------------------------------------------------- 1 | package lico.example.view; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.support.v7.widget.StaggeredGridLayoutManager; 7 | import android.view.View; 8 | 9 | import com.jcodecraeer.xrecyclerview.ProgressStyle; 10 | import com.jcodecraeer.xrecyclerview.XRecyclerView; 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | import butterknife.Bind; 16 | import lico.example.R; 17 | import lico.example.adapter.BaseAdapterHelper; 18 | import lico.example.adapter.BaseQuickAdapter; 19 | import lico.example.adapter.SimpleRecyclerAdapter; 20 | import lico.example.bean.ImagesListEntity; 21 | import lico.example.ui.SpaceImageDetailActivity; 22 | import lico.example.views.PLAImageView; 23 | import lico.example.views.SpacesItemDecoration; 24 | 25 | /** 26 | * Created by zzk on 15/12/7. 27 | */ 28 | public class ImageListView extends ViewImpl { 29 | @Bind(R.id.xrecyclerView) 30 | XRecyclerView xrecyclerView; 31 | 32 | private SimpleRecyclerAdapter mAdapter; 33 | private List mList = new ArrayList<>(); 34 | 35 | @Override 36 | public int getLayoutId() { 37 | return R.layout.fragment_image_list; 38 | } 39 | 40 | public void initViews(Context context, XRecyclerView.LoadingListener listener){ 41 | StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL); 42 | xrecyclerView.setLayoutManager(layoutManager); 43 | xrecyclerView.setLoadingListener(listener); 44 | xrecyclerView.setRefreshProgressStyle(ProgressStyle.BallRotate); 45 | xrecyclerView.setLaodingMoreProgressStyle(ProgressStyle.BallRotate); 46 | xrecyclerView.addItemDecoration(new SpacesItemDecoration(5)); 47 | //xrecyclerView.setArrowImageView(R.drawable.iconfont_downgrey); 48 | mAdapter = new SimpleRecyclerAdapter(context, mList, R.layout.view_image_list_item) { 49 | 50 | @Override 51 | protected void convert(BaseAdapterHelper helper, ImagesListEntity item) { 52 | int width = item.thumbnailWidth; 53 | int height = item.thumbnailHeight; 54 | PLAImageView plaImageView = (PLAImageView) helper.getImageView(R.id.item_image); 55 | plaImageView.setImageHeight(height); 56 | plaImageView.setImageWidth(width); 57 | // helper.setImage(R.id.item_image, item.thumbnailUrl); 58 | helper.setImageByUrl(R.id.item_image, item.thumbnailUrl); 59 | } 60 | }; 61 | 62 | mAdapter.setOnInViewClickListener(R.id.root_layout, new BaseQuickAdapter.onInternalClickListenerImpl(){ 63 | @Override 64 | public void OnClickListener(View parentV, View v, Integer position, ImagesListEntity values) { 65 | int[] location = new int[2]; 66 | v.getLocationOnScreen(location); 67 | int width = v.getWidth(); 68 | int height = v.getHeight(); 69 | gotoDetail((Activity) context, position, values, location[0], location[1], width, height); 70 | } 71 | }); 72 | 73 | xrecyclerView.setAdapter(mAdapter); 74 | } 75 | 76 | public void refreshListData(List imageEntity) { 77 | mAdapter.getDataList().clear(); 78 | mAdapter.getDataList().addAll(imageEntity); 79 | mAdapter.notifyDataSetChanged(); 80 | xrecyclerView.refreshComplete(); 81 | xrecyclerView.scrollToPosition(0); 82 | } 83 | 84 | public void addListData(List imageEntity){ 85 | xrecyclerView.loadMoreComplete(); 86 | mAdapter.getDataList().addAll(imageEntity); 87 | //用notifyDataSetChanged();会出现花屏问题 88 | mAdapter.notifyItemRangeChanged(mAdapter.getDataList().size() - 10, 10); 89 | xrecyclerView.refreshComplete(); 90 | } 91 | 92 | private void gotoDetail(Activity activity, int position, ImagesListEntity imagesListEntity, int x, int y, int width, int height){ 93 | Intent intent = new Intent(activity, SpaceImageDetailActivity.class); 94 | intent.putExtra("images", imagesListEntity.imageUrl); 95 | intent.putExtra("locationX", x); 96 | intent.putExtra("locationY", y); 97 | intent.putExtra("width", width); 98 | intent.putExtra("height", height); 99 | activity.startActivity(intent); 100 | activity.overridePendingTransition(0, 0); 101 | } 102 | 103 | @Override 104 | public void destroy() { 105 | 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/view/ImagesView.java: -------------------------------------------------------------------------------- 1 | package lico.example.view; 2 | 3 | import android.support.design.widget.TabLayout; 4 | import android.support.v4.app.FragmentManager; 5 | import android.support.v4.view.ViewPager; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | import butterknife.Bind; 11 | import lico.example.R; 12 | import lico.example.adapter.TabFragmentPagerAdapter; 13 | 14 | /** 15 | * Created by zzk on 15/12/1. 16 | */ 17 | public class ImagesView extends ViewImpl { 18 | @Bind(R.id.tabs) 19 | TabLayout tabs; 20 | @Bind(R.id.viewpager) 21 | ViewPager viewpager; 22 | 23 | private TabFragmentPagerAdapter mPagerAdapter; 24 | 25 | @Override 26 | public int getLayoutId() { 27 | return R.layout.fragment_images; 28 | } 29 | 30 | public void initViewPager(String[] titles, FragmentManager manager){ 31 | viewpager.setOffscreenPageLimit(titles.length + 1); 32 | List title = new ArrayList<>(); 33 | for (String titles1 : titles) 34 | title.add(titles1); 35 | mPagerAdapter = new TabFragmentPagerAdapter(manager, title, 1); 36 | viewpager.setAdapter(mPagerAdapter); 37 | tabs.setupWithViewPager(viewpager); 38 | tabs.setTabsFromPagerAdapter(mPagerAdapter); 39 | } 40 | 41 | @Override 42 | public void destroy() { 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/view/MainView.java: -------------------------------------------------------------------------------- 1 | package lico.example.view; 2 | 3 | import android.app.Activity; 4 | import android.graphics.Bitmap; 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.app.FragmentManager; 9 | import android.support.v4.app.FragmentTransaction; 10 | import android.support.v4.view.GravityCompat; 11 | import android.support.v4.widget.DrawerLayout; 12 | import android.support.v7.app.ActionBarDrawerToggle; 13 | import android.support.v7.widget.Toolbar; 14 | import android.view.View; 15 | import android.widget.ImageView; 16 | 17 | import butterknife.Bind; 18 | import butterknife.ButterKnife; 19 | import lico.example.R; 20 | import lico.example.fragment.ContentFragment; 21 | import lico.example.fragment.ImageFragment; 22 | import lico.example.helper.EventHelper; 23 | 24 | /** 25 | * Created by zzk on 15/11/26. 26 | */ 27 | public class MainView extends ViewImpl { 28 | @Bind(R.id.toolbar) 29 | Toolbar toolbar; 30 | @Bind(R.id.fab) 31 | FloatingActionButton fab; 32 | @Bind(R.id.nav_view) 33 | NavigationView navView; 34 | @Bind(R.id.drawer_layout) 35 | DrawerLayout drawerLayout; 36 | 37 | 38 | private ImageView mHeadBgImg, mAvatorImg; 39 | private ImageFragment mImageFragment; 40 | private ContentFragment mContentFragment; 41 | 42 | @Override 43 | public int getLayoutId() { 44 | return R.layout.activity_main; 45 | } 46 | 47 | @Override 48 | public void bindEvent() { 49 | super.bindEvent(); 50 | ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( 51 | (Activity) mRootView.getContext(), drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); 52 | drawerLayout.setDrawerListener(toggle); 53 | toggle.syncState(); 54 | 55 | View headerView = navView.inflateHeaderView(R.layout.nav_header_main); 56 | mHeadBgImg = (ImageView) headerView.findViewById(R.id.head_image); 57 | mAvatorImg = (ImageView) headerView.findViewById(R.id.imageView); 58 | 59 | EventHelper.click(mPresenter, fab, mAvatorImg); 60 | EventHelper.setNavigationItemSelected(mPresenter, navView); 61 | } 62 | 63 | public void setAvator(Bitmap bitmap) { 64 | mHeadBgImg.setImageBitmap(bitmap); 65 | } 66 | 67 | public boolean setNavigationItemSelected(FragmentManager manager, int menuId) { 68 | boolean isConsume = false; 69 | setNewRootFragment(manager, menuId); 70 | drawerLayout.closeDrawer(GravityCompat.START); 71 | return isConsume; 72 | } 73 | 74 | public boolean setOptionsItemSelected(int itemId) { 75 | boolean isConsume = false; 76 | switch (itemId) { 77 | case R.id.action_settings: 78 | Snackbar.make(mRootView.getRootView(), "点击了Setting", Snackbar.LENGTH_SHORT).setAction("Action", null).show(); 79 | isConsume = true; 80 | break; 81 | } 82 | return isConsume; 83 | } 84 | 85 | public boolean closeDrawer() { 86 | if (drawerLayout.isDrawerOpen(GravityCompat.START)) { 87 | drawerLayout.closeDrawer(GravityCompat.START); 88 | return true; 89 | } else return false; 90 | } 91 | 92 | public void setFabClick(String string) { 93 | Snackbar.make(mRootView.getRootView(), string, Snackbar.LENGTH_SHORT).setAction("Action", null).show(); 94 | } 95 | 96 | public int getOptionsMenuId() { 97 | return R.menu.main; 98 | } 99 | 100 | @Override 101 | public Toolbar getToolbar() { 102 | return toolbar; 103 | } 104 | 105 | @Override 106 | public void destroy() { 107 | ButterKnife.unbind(mRootView.getRootView()); 108 | } 109 | 110 | private void setNewRootFragment(FragmentManager manager, int menuId) { 111 | FragmentTransaction transaction = manager.beginTransaction(); 112 | hideFragment(transaction); 113 | switch (menuId) { 114 | case R.id.nav_camera: 115 | mImageFragment = (ImageFragment) manager.findFragmentByTag("images"); 116 | if (mImageFragment == null) { 117 | mImageFragment = new ImageFragment(); 118 | transaction.add(R.id.container, mImageFragment, "images"); 119 | } else { 120 | transaction.show(mImageFragment); 121 | } 122 | break; 123 | case R.id.nav_gallery: 124 | mContentFragment = (ContentFragment) manager.findFragmentByTag("contentlist"); 125 | if (mContentFragment == null) { 126 | mContentFragment = new ContentFragment(); 127 | transaction.add(R.id.container, mContentFragment, "contentlist"); 128 | } else { 129 | transaction.show(mContentFragment); 130 | } 131 | break; 132 | case R.id.nav_slideshow: 133 | 134 | break; 135 | case R.id.nav_manage: 136 | break; 137 | case R.id.nav_share: 138 | break; 139 | case R.id.nav_send: 140 | break; 141 | } 142 | transaction.commit(); 143 | drawerLayout.closeDrawers(); 144 | } 145 | 146 | private void hideFragment(FragmentTransaction transaction) { 147 | if (mImageFragment != null) { 148 | transaction.hide(mImageFragment); 149 | } 150 | if (mContentFragment != null) { 151 | transaction.hide(mContentFragment); 152 | } 153 | } 154 | 155 | } 156 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/view/PersonalView.java: -------------------------------------------------------------------------------- 1 | package lico.example.view; 2 | 3 | import android.graphics.Color; 4 | import android.support.design.widget.AppBarLayout; 5 | import android.support.design.widget.CollapsingToolbarLayout; 6 | import android.support.v7.widget.RecyclerView; 7 | import android.support.v7.widget.Toolbar; 8 | import android.widget.ImageView; 9 | 10 | import butterknife.Bind; 11 | import lico.example.R; 12 | 13 | /** 14 | * Created by zzk on 15/11/28. 15 | */ 16 | public class PersonalView extends ViewImpl { 17 | @Bind(R.id.backgroud) 18 | ImageView backgroud; 19 | @Bind(R.id.toolbar) 20 | Toolbar toolbar; 21 | @Bind(R.id.appbar) 22 | AppBarLayout appbar; 23 | @Bind(R.id.recyclerView) 24 | RecyclerView recyclerView; 25 | @Bind(R.id.collapsing_toolbar) 26 | CollapsingToolbarLayout collapsingToolbar; 27 | 28 | @Override 29 | public int getLayoutId() { 30 | return R.layout.activity_personal; 31 | } 32 | 33 | @Override 34 | public void bindEvent() { 35 | super.bindEvent(); 36 | collapsingToolbar.setTitle("Lico"); 37 | collapsingToolbar.setExpandedTitleColor(Color.WHITE); 38 | collapsingToolbar.setCollapsedTitleTextColor(Color.GREEN); 39 | 40 | } 41 | 42 | @Override 43 | public Toolbar getToolbar() { 44 | return toolbar; 45 | } 46 | 47 | @Override 48 | public void destroy() { 49 | 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/view/ViewImpl.java: -------------------------------------------------------------------------------- 1 | package lico.example.view; 2 | 3 | import android.view.LayoutInflater; 4 | import android.view.View; 5 | import android.view.ViewGroup; 6 | import android.support.v7.widget.Toolbar; 7 | 8 | import butterknife.ButterKnife; 9 | import lico.example.presenter.IPresenter; 10 | 11 | /** 12 | * Created by zzk on 15/11/26. 13 | */ 14 | public abstract class ViewImpl implements IView { 15 | protected View mRootView; 16 | protected IPresenter mPresenter; 17 | 18 | @Override 19 | public void create(LayoutInflater inflater, ViewGroup container) { 20 | mRootView = inflater.inflate(getLayoutId(), container, false); 21 | ButterKnife.bind(this, mRootView.getRootView()); 22 | } 23 | 24 | @Override 25 | public View getRootView() { return mRootView; } 26 | 27 | @Override 28 | public int getOptionsMenuId() { 29 | return 0; 30 | } 31 | 32 | @Override 33 | public Toolbar getToolbar() { return null; } 34 | 35 | @Override 36 | public void bindPresenter(IPresenter presenter) { mPresenter = presenter; } 37 | 38 | @Override 39 | public void bindEvent() {} 40 | 41 | public abstract int getLayoutId(); 42 | 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/views/PLAImageView.java: -------------------------------------------------------------------------------- 1 | package lico.example.views; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.drawable.Drawable; 6 | import android.util.AttributeSet; 7 | import android.view.View; 8 | import android.widget.ImageView; 9 | import android.widget.RelativeLayout; 10 | 11 | /** 12 | * This view will auto determine the width or height by determining if the 13 | * height or width is set and scale the other dimension depending on the images 14 | * dimension 15 | *

16 | * This view also contains an ImageChangeListener which calls changed(boolean 17 | * isEmpty) once a change has been made to the ImageView 18 | * 19 | * @author Maurycy Wojtowicz 20 | */ 21 | public class PLAImageView extends ImageView { 22 | private Bitmap currentBitmap; 23 | private ImageChangeListener imageChangeListener; 24 | private boolean scaleToWidth = false; // this flag determines if should 25 | // measure height manually dependent 26 | // of width 27 | 28 | public PLAImageView(Context context) { 29 | super(context); 30 | init(); 31 | } 32 | 33 | public PLAImageView(Context context, AttributeSet attrs, int defStyle) { 34 | super(context, attrs, defStyle); 35 | init(); 36 | } 37 | 38 | public PLAImageView(Context context, AttributeSet attrs) { 39 | super(context, attrs); 40 | init(); 41 | } 42 | 43 | private void init() { 44 | this.setScaleType(ImageView.ScaleType.CENTER_INSIDE); 45 | } 46 | 47 | public void recycle() { 48 | setImageBitmap(null); 49 | if ((this.currentBitmap == null) || (this.currentBitmap.isRecycled())) 50 | return; 51 | this.currentBitmap.recycle(); 52 | this.currentBitmap = null; 53 | } 54 | 55 | @Override 56 | public void setImageBitmap(Bitmap bm) { 57 | currentBitmap = bm; 58 | super.setImageBitmap(currentBitmap); 59 | if (imageChangeListener != null) 60 | imageChangeListener.changed((currentBitmap == null)); 61 | } 62 | 63 | @Override 64 | public void setImageDrawable(Drawable d) { 65 | super.setImageDrawable(d); 66 | if (imageChangeListener != null) 67 | imageChangeListener.changed((d == null)); 68 | } 69 | 70 | @Override 71 | public void setImageResource(int id) { 72 | super.setImageResource(id); 73 | } 74 | 75 | public interface ImageChangeListener { 76 | // a callback for when a change has been made to this imageView 77 | void changed(boolean isEmpty); 78 | } 79 | 80 | public ImageChangeListener getImageChangeListener() { 81 | return imageChangeListener; 82 | } 83 | 84 | public void setImageChangeListener(ImageChangeListener imageChangeListener) { 85 | this.imageChangeListener = imageChangeListener; 86 | } 87 | 88 | private int imageWidth; 89 | private int imageHeight; 90 | 91 | public void setImageWidth(int w) { 92 | imageWidth = w; 93 | } 94 | 95 | public void setImageHeight(int h) { 96 | imageHeight = h; 97 | } 98 | 99 | @Override 100 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 101 | 102 | int widthMode = View.MeasureSpec.getMode(widthMeasureSpec); 103 | int heightMode = View.MeasureSpec.getMode(heightMeasureSpec); 104 | int width = View.MeasureSpec.getSize(widthMeasureSpec); 105 | int height = View.MeasureSpec.getSize(heightMeasureSpec); 106 | 107 | /** 108 | * if both width and height are set scale width first. modify in future 109 | * if necessary 110 | */ 111 | 112 | if (widthMode == View.MeasureSpec.EXACTLY || widthMode == View.MeasureSpec.AT_MOST) { 113 | scaleToWidth = true; 114 | } else if (heightMode == View.MeasureSpec.EXACTLY || heightMode == View.MeasureSpec.AT_MOST) { 115 | scaleToWidth = false; 116 | } else 117 | throw new IllegalStateException("width or height needs to be set to match_parent or a specific dimension"); 118 | 119 | if (imageWidth == 0) { 120 | // nothing to measure 121 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 122 | return; 123 | } else { 124 | if (scaleToWidth) { 125 | int iw = imageWidth; 126 | int ih = imageHeight; 127 | int heightC = width * ih / iw; 128 | if (height > 0) 129 | if (heightC > height) { 130 | // dont let hegiht be greater then set max 131 | heightC = height; 132 | width = heightC * iw / ih; 133 | } 134 | 135 | this.setScaleType(ImageView.ScaleType.CENTER_CROP); 136 | setMeasuredDimension(width, heightC); 137 | 138 | } else { 139 | // need to scale to height instead 140 | int marg = 0; 141 | if (getParent() != null) { 142 | if (getParent().getParent() != null) { 143 | marg += ((RelativeLayout) getParent().getParent()).getPaddingTop(); 144 | marg += ((RelativeLayout) getParent().getParent()).getPaddingBottom(); 145 | } 146 | } 147 | 148 | int iw = imageWidth; 149 | int ih = imageHeight; 150 | 151 | width = height * iw / ih; 152 | height -= marg; 153 | setMeasuredDimension(width, height); 154 | } 155 | 156 | } 157 | } 158 | 159 | } 160 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/views/PullLoadMoreRecyclerView.java: -------------------------------------------------------------------------------- 1 | package lico.example.views; 2 | 3 | import android.content.Context; 4 | import android.support.v4.widget.SwipeRefreshLayout; 5 | import android.support.v7.widget.DefaultItemAnimator; 6 | import android.support.v7.widget.GridLayoutManager; 7 | import android.support.v7.widget.LinearLayoutManager; 8 | import android.support.v7.widget.RecyclerView; 9 | import android.support.v7.widget.StaggeredGridLayoutManager; 10 | import android.util.AttributeSet; 11 | import android.view.LayoutInflater; 12 | import android.view.MotionEvent; 13 | import android.view.View; 14 | import android.widget.LinearLayout; 15 | 16 | import lico.example.R; 17 | 18 | /** 19 | * Created by zzk on 15/12/22. 20 | */ 21 | public class PullLoadMoreRecyclerView extends LinearLayout{ 22 | 23 | private RecyclerView mRecyclerView; 24 | private SwipeRefreshLayout mSwipeRefreshLayout; 25 | private PullLoadMoreListener mPullLoadMoreListener; 26 | private boolean hasMore = true; 27 | private boolean isRefresh = false; 28 | private boolean isLoadMore = false; 29 | private Context mContext; 30 | 31 | 32 | public PullLoadMoreRecyclerView(Context context) { 33 | super(context); 34 | initView(context); 35 | } 36 | 37 | public PullLoadMoreRecyclerView(Context context, AttributeSet attrs) { 38 | super(context, attrs); 39 | initView(context); 40 | } 41 | 42 | private void initView(Context context){ 43 | mContext = context; 44 | View view = LayoutInflater.from(context).inflate(R.layout.view_pull_load_more, null); 45 | mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipe_refreshlayout); 46 | mSwipeRefreshLayout.setColorSchemeResources(android.R.color.holo_green_dark, android.R.color.holo_blue_dark, android.R.color.holo_orange_dark); 47 | mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayoutOnRefresh(this)); 48 | 49 | mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view); 50 | mRecyclerView.setVerticalScrollBarEnabled(true); 51 | 52 | mRecyclerView.setHasFixedSize(true); 53 | mRecyclerView.setItemAnimator(new DefaultItemAnimator()); 54 | //mRecyclerView.addItemDecoration(new DividerItemDecoration( 55 | //getActivity(), DividerItemDecoration.HORIZONTAL_LIST)); 56 | mRecyclerView.addOnScrollListener(new RecyclerViewOnScroll(this)); 57 | //Solve IndexOutOfBoundsException exception 58 | mRecyclerView.setOnTouchListener( 59 | new View.OnTouchListener() { 60 | @Override 61 | public boolean onTouch(View v, MotionEvent event) { 62 | if (isRefresh) { 63 | return true; 64 | } else { 65 | return false; 66 | } 67 | } 68 | } 69 | ); 70 | this.addView(view); 71 | 72 | } 73 | 74 | /** 75 | * LinearLayoutManager 76 | */ 77 | public void setLinearLayout() { 78 | LinearLayoutManager linearLayoutManager = new LinearLayoutManager(mContext); 79 | linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); 80 | mRecyclerView.setLayoutManager(linearLayoutManager); 81 | } 82 | 83 | /** 84 | * GridLayoutManager 85 | */ 86 | 87 | public void setGridLayout(int spanCount) { 88 | 89 | GridLayoutManager gridLayoutManager = new GridLayoutManager(mContext, spanCount); 90 | gridLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); 91 | mRecyclerView.setLayoutManager(gridLayoutManager); 92 | } 93 | 94 | 95 | /** 96 | * StaggeredGridLayoutManager 97 | */ 98 | 99 | public void setStaggeredGridLayout(int spanCount) { 100 | StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(spanCount, LinearLayoutManager.VERTICAL); 101 | mRecyclerView.setLayoutManager(staggeredGridLayoutManager); 102 | } 103 | 104 | public void setPullRefreshEnable(boolean enable) { 105 | mSwipeRefreshLayout.setEnabled(enable); 106 | } 107 | 108 | public boolean getPullRefreshEnable() { 109 | return mSwipeRefreshLayout.isEnabled(); 110 | } 111 | 112 | public RecyclerView.LayoutManager getLayoutManager() { 113 | return mRecyclerView.getLayoutManager(); 114 | } 115 | 116 | 117 | public void loadMore() { 118 | if (mPullLoadMoreListener != null && hasMore) { 119 | mPullLoadMoreListener.onLoadMore(); 120 | 121 | } 122 | } 123 | 124 | 125 | public void setPullLoadMoreCompleted() { 126 | isRefresh = false; 127 | mSwipeRefreshLayout.setRefreshing(false); 128 | 129 | isLoadMore = false; 130 | 131 | } 132 | 133 | public void setRefreshing(final boolean isRefreshing) { 134 | mSwipeRefreshLayout.post(new Runnable() { 135 | 136 | @Override 137 | public void run() { 138 | mSwipeRefreshLayout.setRefreshing(isRefreshing); 139 | } 140 | }); 141 | 142 | } 143 | 144 | 145 | public void setOnPullLoadMoreListener(PullLoadMoreListener listener) { 146 | mPullLoadMoreListener = listener; 147 | } 148 | 149 | public void refresh() { 150 | mRecyclerView.setVisibility(View.VISIBLE); 151 | if (mPullLoadMoreListener != null) { 152 | mPullLoadMoreListener.onRefresh(); 153 | } 154 | } 155 | 156 | public void scrollToTop() { 157 | mRecyclerView.scrollToPosition(0); 158 | } 159 | 160 | 161 | public void setAdapter(RecyclerView.Adapter adapter) { 162 | if (adapter != null) { 163 | mRecyclerView.setAdapter(adapter); 164 | } 165 | } 166 | 167 | public boolean isLoadMore() { 168 | return isLoadMore; 169 | } 170 | 171 | public void setIsLoadMore(boolean isLoadMore) { 172 | this.isLoadMore = isLoadMore; 173 | } 174 | 175 | public boolean isRefresh() { 176 | return isRefresh; 177 | } 178 | 179 | public void setIsRefresh(boolean isRefresh) { 180 | this.isRefresh = isRefresh; 181 | } 182 | 183 | public boolean isHasMore() { 184 | return hasMore; 185 | } 186 | 187 | public void setHasMore(boolean hasMore) { 188 | this.hasMore = hasMore; 189 | } 190 | 191 | public interface PullLoadMoreListener { 192 | public void onRefresh(); 193 | 194 | public void onLoadMore(); 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/views/RecyclerViewOnScroll.java: -------------------------------------------------------------------------------- 1 | package lico.example.views; 2 | 3 | import android.support.v7.widget.GridLayoutManager; 4 | import android.support.v7.widget.LinearLayoutManager; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.support.v7.widget.StaggeredGridLayoutManager; 7 | 8 | /** 9 | * Created by zzk on 15/12/23. 10 | */ 11 | public class RecyclerViewOnScroll extends RecyclerView.OnScrollListener { 12 | PullLoadMoreRecyclerView mPullLoadMoreRecyclerView; 13 | 14 | public RecyclerViewOnScroll(PullLoadMoreRecyclerView pullLoadMoreRecyclerView) { 15 | this.mPullLoadMoreRecyclerView = pullLoadMoreRecyclerView; 16 | } 17 | 18 | @Override 19 | public void onScrolled(RecyclerView recyclerView, int dx, int dy) { 20 | super.onScrolled(recyclerView, dx, dy); 21 | int lastVisibleItem = 0; 22 | int firstVisibleItem = 0; 23 | RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); 24 | int totalItemCount = layoutManager.getItemCount(); 25 | if (layoutManager instanceof LinearLayoutManager) { 26 | LinearLayoutManager linearLayoutManager = ((LinearLayoutManager) layoutManager); 27 | lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition(); 28 | firstVisibleItem = linearLayoutManager.findFirstCompletelyVisibleItemPosition(); 29 | } else if (layoutManager instanceof GridLayoutManager) { 30 | GridLayoutManager gridLayoutManager = ((GridLayoutManager) layoutManager); 31 | //Position to find the final item of the current LayoutManager 32 | lastVisibleItem = gridLayoutManager.findLastVisibleItemPosition(); 33 | firstVisibleItem = gridLayoutManager.findFirstCompletelyVisibleItemPosition(); 34 | } else if (layoutManager instanceof StaggeredGridLayoutManager) { 35 | StaggeredGridLayoutManager staggeredGridLayoutManager = ((StaggeredGridLayoutManager) layoutManager); 36 | // since may lead to the final item has more than one StaggeredGridLayoutManager the particularity of the so here that is an array 37 | // this array into an array of position and then take the maximum value that is the last show the position value 38 | int[] lastPositions = new int[((StaggeredGridLayoutManager) layoutManager).getSpanCount()]; 39 | staggeredGridLayoutManager.findLastVisibleItemPositions(lastPositions); 40 | lastVisibleItem = findMax(lastPositions); 41 | firstVisibleItem = staggeredGridLayoutManager.findFirstVisibleItemPositions(lastPositions)[0]; 42 | } 43 | if (firstVisibleItem == 0) { 44 | if (!mPullLoadMoreRecyclerView.isLoadMore()) { 45 | mPullLoadMoreRecyclerView.setPullRefreshEnable(true); 46 | } 47 | } else { 48 | mPullLoadMoreRecyclerView.setPullRefreshEnable(false); 49 | } 50 | 51 | /** 52 | * Either horizontal or vertical 53 | */ 54 | if (!mPullLoadMoreRecyclerView.isRefresh() && mPullLoadMoreRecyclerView.isHasMore() && (lastVisibleItem >= totalItemCount - 1) 55 | && !mPullLoadMoreRecyclerView.isLoadMore() && (dx > 0 || dy > 0)) { 56 | mPullLoadMoreRecyclerView.setIsLoadMore(true); 57 | mPullLoadMoreRecyclerView.loadMore(); 58 | } 59 | 60 | } 61 | //To find the maximum value in the array 62 | 63 | private int findMax(int[] lastPositions) { 64 | 65 | int max = lastPositions[0]; 66 | for (int value : lastPositions) { 67 | // int max = Math.max(lastPositions,value); 68 | if (value > max) { 69 | max = value; 70 | } 71 | } 72 | return max; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/views/SmoothImageView.java: -------------------------------------------------------------------------------- 1 | package lico.example.views; 2 | 3 | import android.animation.Animator; 4 | import android.animation.PropertyValuesHolder; 5 | import android.animation.ValueAnimator; 6 | import android.app.Activity; 7 | import android.content.Context; 8 | import android.graphics.Bitmap; 9 | import android.graphics.Canvas; 10 | import android.graphics.Matrix; 11 | import android.graphics.Paint; 12 | import android.graphics.Paint.Style; 13 | import android.graphics.drawable.BitmapDrawable; 14 | import android.util.AttributeSet; 15 | import android.util.Log; 16 | import android.view.animation.AccelerateDecelerateInterpolator; 17 | import android.widget.ImageView; 18 | 19 | import com.bumptech.glide.load.resource.bitmap.GlideBitmapDrawable; 20 | 21 | /** 22 | * 2d平滑变化的显示图片的ImageView 23 | * 仅限于用于:从一个ScaleType==CENTER_CROP的ImageView,切换到另一个ScaleType= 24 | * FIT_CENTER的ImageView,或者反之 (当然,得使用同样的图片最好) 25 | * 26 | * @author Dean Tao 27 | * 28 | */ 29 | public class SmoothImageView extends ImageView { 30 | 31 | private static final int STATE_NORMAL = 0; 32 | private static final int STATE_TRANSFORM_IN = 1; 33 | private static final int STATE_TRANSFORM_OUT = 2; 34 | private int mOriginalWidth; 35 | private int mOriginalHeight; 36 | private int mOriginalLocationX; 37 | private int mOriginalLocationY; 38 | private int mState = STATE_NORMAL; 39 | private Matrix mSmoothMatrix; 40 | private Bitmap mBitmap; 41 | private boolean mTransformStart = false; 42 | private Transfrom mTransfrom; 43 | 44 | private Paint mPaint; 45 | 46 | public SmoothImageView(Context context) { 47 | super(context); 48 | init(); 49 | } 50 | 51 | public SmoothImageView(Context context, AttributeSet attrs) { 52 | super(context, attrs); 53 | init(); 54 | } 55 | 56 | public SmoothImageView(Context context, AttributeSet attrs, int defStyle) { 57 | super(context, attrs, defStyle); 58 | init(); 59 | } 60 | 61 | private void init() { 62 | mSmoothMatrix = new Matrix(); 63 | mPaint=new Paint(); 64 | mPaint.setColor(mBgColor); 65 | mPaint.setStyle(Style.FILL); 66 | // setBackgroundColor(mBgColor); 67 | } 68 | 69 | public void setOriginalInfo(int width, int height, int locationX, int locationY) { 70 | mOriginalWidth = width; 71 | mOriginalHeight = height; 72 | mOriginalLocationX = locationX; 73 | mOriginalLocationY = locationY; 74 | // 因为是屏幕坐标,所以要转换为该视图内的坐标,因为我所用的该视图是MATCH_PARENT,所以不用定位该视图的位置,如果不是的话,还需要定位视图的位置,然后计算mOriginalLocationX和mOriginalLocationY 75 | mOriginalLocationY = mOriginalLocationY - getStatusBarHeight(getContext()); 76 | } 77 | 78 | /** 79 | * 获取状态栏高度 80 | * 81 | * @return 82 | */ 83 | public static int getStatusBarHeight(Context context) { 84 | Class c = null; 85 | Object obj = null; 86 | java.lang.reflect.Field field = null; 87 | int x = 0; 88 | int statusBarHeight = 0; 89 | try { 90 | c = Class.forName("com.android.internal.R$dimen"); 91 | obj = c.newInstance(); 92 | field = c.getField("status_bar_height"); 93 | x = Integer.parseInt(field.get(obj).toString()); 94 | statusBarHeight = context.getResources().getDimensionPixelSize(x); 95 | return statusBarHeight; 96 | } catch (Exception e) { 97 | e.printStackTrace(); 98 | } 99 | return statusBarHeight; 100 | } 101 | 102 | /** 103 | * 用于开始进入的方法。 调用此方前,需已经调用过setOriginalInfo 104 | */ 105 | public void transformIn() { 106 | mState = STATE_TRANSFORM_IN; 107 | mTransformStart = true; 108 | invalidate(); 109 | } 110 | 111 | /** 112 | * 用于开始退出的方法。 调用此方前,需已经调用过setOriginalInfo 113 | */ 114 | public void transformOut() { 115 | mState = STATE_TRANSFORM_OUT; 116 | mTransformStart = true; 117 | invalidate(); 118 | } 119 | 120 | private class Transfrom { 121 | float startScale;// 图片开始的缩放值 122 | float endScale;// 图片结束的缩放值 123 | float scale;// 属性ValueAnimator计算出来的值 124 | LocationSizeF startRect;// 开始的区域 125 | LocationSizeF endRect;// 结束的区域 126 | LocationSizeF rect;// 属性ValueAnimator计算出来的值 127 | 128 | void initStartIn() { 129 | scale = startScale; 130 | try { 131 | rect = (LocationSizeF) startRect.clone(); 132 | } catch (CloneNotSupportedException e) { 133 | e.printStackTrace(); 134 | } 135 | } 136 | 137 | void initStartOut() { 138 | scale = endScale; 139 | try { 140 | rect = (LocationSizeF) endRect.clone(); 141 | } catch (CloneNotSupportedException e) { 142 | e.printStackTrace(); 143 | } 144 | } 145 | 146 | } 147 | 148 | /** 149 | * 初始化进入的变量信息 150 | */ 151 | private void initTransform() { 152 | if (getDrawable() == null) { 153 | return; 154 | } 155 | if (mBitmap == null || mBitmap.isRecycled()) { 156 | // mBitmap = ((BitmapDrawable) getDrawable()).getBitmap(); 157 | mBitmap = ((GlideBitmapDrawable)getDrawable()).getBitmap(); 158 | } 159 | //防止mTransfrom重复的做同样的初始化 160 | if (mTransfrom != null) { 161 | return; 162 | } 163 | if (getWidth() == 0 || getHeight() == 0) { 164 | return; 165 | } 166 | mTransfrom = new Transfrom(); 167 | 168 | /** 下面为缩放的计算 */ 169 | /* 计算初始的缩放值,初始值因为是CENTR_CROP效果,所以要保证图片的宽和高至少1个能匹配原始的宽和高,另1个大于 */ 170 | float xSScale = mOriginalWidth / ((float) mBitmap.getWidth()); 171 | float ySScale = mOriginalHeight / ((float) mBitmap.getHeight()); 172 | float startScale = xSScale > ySScale ? xSScale : ySScale; 173 | mTransfrom.startScale = startScale; 174 | /* 计算结束时候的缩放值,结束值因为要达到FIT_CENTER效果,所以要保证图片的宽和高至少1个能匹配原始的宽和高,另1个小于 */ 175 | float xEScale = getWidth() / ((float) mBitmap.getWidth()); 176 | float yEScale = getHeight() / ((float) mBitmap.getHeight()); 177 | float endScale = xEScale < yEScale ? xEScale : yEScale; 178 | mTransfrom.endScale = endScale; 179 | 180 | /** 181 | * 下面计算Canvas Clip的范围,也就是图片的显示的范围,因为图片是慢慢变大,并且是等比例的,所以这个效果还需要裁减图片显示的区域 182 | * ,而显示区域的变化范围是在原始CENTER_CROP效果的范围区域 183 | * ,到最终的FIT_CENTER的范围之间的,区域我用LocationSizeF更好计算 184 | * ,他就包括左上顶点坐标,和宽高,最后转为Canvas裁减的Rect. 185 | */ 186 | /* 开始区域 */ 187 | mTransfrom.startRect = new LocationSizeF(); 188 | mTransfrom.startRect.left = mOriginalLocationX; 189 | mTransfrom.startRect.top = mOriginalLocationY; 190 | mTransfrom.startRect.width = mOriginalWidth; 191 | mTransfrom.startRect.height = mOriginalHeight; 192 | /* 结束区域 */ 193 | mTransfrom.endRect = new LocationSizeF(); 194 | float bitmapEndWidth = mBitmap.getWidth() * mTransfrom.endScale;// 图片最终的宽度 195 | float bitmapEndHeight = mBitmap.getHeight() * mTransfrom.endScale;// 图片最终的宽度 196 | mTransfrom.endRect.left = (getWidth() - bitmapEndWidth) / 2; 197 | mTransfrom.endRect.top = (getHeight() - bitmapEndHeight) / 2; 198 | mTransfrom.endRect.width = bitmapEndWidth; 199 | mTransfrom.endRect.height = bitmapEndHeight; 200 | 201 | mTransfrom.rect = new LocationSizeF(); 202 | } 203 | 204 | private class LocationSizeF implements Cloneable { 205 | float left; 206 | float top; 207 | float width; 208 | float height; 209 | @Override 210 | public String toString() { 211 | return "[left:"+left+" top:"+top+" width:"+width+" height:"+height+"]"; 212 | } 213 | 214 | @Override 215 | public Object clone() throws CloneNotSupportedException { 216 | // TODO Auto-generated method stub 217 | return super.clone(); 218 | } 219 | 220 | } 221 | 222 | /* 下面实现了CENTER_CROP的功能 的Matrix,在优化的过程中,已经不用了 */ 223 | private void getCenterCropMatrix() { 224 | if (getDrawable() == null) { 225 | return; 226 | } 227 | if (mBitmap == null || mBitmap.isRecycled()) { 228 | mBitmap = ((BitmapDrawable) getDrawable()).getBitmap(); 229 | } 230 | /* 下面实现了CENTER_CROP的功能 */ 231 | float xScale = mOriginalWidth / ((float) mBitmap.getWidth()); 232 | float yScale = mOriginalHeight / ((float) mBitmap.getHeight()); 233 | float scale = xScale > yScale ? xScale : yScale; 234 | mSmoothMatrix.reset(); 235 | mSmoothMatrix.setScale(scale, scale); 236 | mSmoothMatrix.postTranslate(-(scale * mBitmap.getWidth() / 2 - mOriginalWidth / 2), -(scale * mBitmap.getHeight() / 2 - mOriginalHeight / 2)); 237 | } 238 | 239 | private void getBmpMatrix() { 240 | if (getDrawable() == null) { 241 | return; 242 | } 243 | if (mTransfrom == null) { 244 | return; 245 | } 246 | if (mBitmap == null || mBitmap.isRecycled()) { 247 | mBitmap = ((BitmapDrawable) getDrawable()).getBitmap(); 248 | } 249 | /* 下面实现了CENTER_CROP的功能 */ 250 | mSmoothMatrix.setScale(mTransfrom.scale, mTransfrom.scale); 251 | mSmoothMatrix.postTranslate(-(mTransfrom.scale * mBitmap.getWidth() / 2 - mTransfrom.rect.width / 2), 252 | -(mTransfrom.scale * mBitmap.getHeight() / 2 - mTransfrom.rect.height / 2)); 253 | } 254 | 255 | @Override 256 | protected void onDraw(Canvas canvas) { 257 | if (getDrawable() == null) { 258 | return; // couldn't resolve the URI 259 | } 260 | 261 | if (mState == STATE_TRANSFORM_IN || mState == STATE_TRANSFORM_OUT) { 262 | if (mTransformStart) { 263 | initTransform(); 264 | } 265 | if (mTransfrom == null) { 266 | super.onDraw(canvas); 267 | return; 268 | } 269 | 270 | if (mTransformStart) { 271 | if (mState == STATE_TRANSFORM_IN) { 272 | mTransfrom.initStartIn(); 273 | } else { 274 | mTransfrom.initStartOut(); 275 | } 276 | } 277 | 278 | if(mTransformStart){ 279 | Log.d("Dean", "mTransfrom.startScale:" + mTransfrom.startScale); 280 | Log.d("Dean", "mTransfrom.startScale:" + mTransfrom.endScale); 281 | Log.d("Dean", "mTransfrom.scale:" + mTransfrom.scale); 282 | Log.d("Dean", "mTransfrom.startRect:" + mTransfrom.startRect.toString()); 283 | Log.d("Dean", "mTransfrom.endRect:" + mTransfrom.endRect.toString()); 284 | Log.d("Dean", "mTransfrom.rect:" + mTransfrom.rect.toString()); 285 | } 286 | 287 | mPaint.setAlpha(mBgAlpha); 288 | canvas.drawPaint(mPaint); 289 | 290 | int saveCount = canvas.getSaveCount(); 291 | canvas.save(); 292 | // 先得到图片在此刻的图像Matrix矩阵 293 | getBmpMatrix(); 294 | canvas.translate(mTransfrom.rect.left, mTransfrom.rect.top); 295 | canvas.clipRect(0, 0, mTransfrom.rect.width, mTransfrom.rect.height); 296 | canvas.concat(mSmoothMatrix); 297 | getDrawable().draw(canvas); 298 | canvas.restoreToCount(saveCount); 299 | if (mTransformStart) { 300 | mTransformStart=false; 301 | startTransform(mState); 302 | } 303 | } else { 304 | //当Transform In变化完成后,把背景改为黑色,使得Activity不透明 305 | mPaint.setAlpha(255); 306 | canvas.drawPaint(mPaint); 307 | super.onDraw(canvas); 308 | } 309 | } 310 | 311 | private void startTransform(final int state) { 312 | if (mTransfrom == null) { 313 | return; 314 | } 315 | ValueAnimator valueAnimator = new ValueAnimator(); 316 | valueAnimator.setDuration(300); 317 | valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); 318 | if (state == STATE_TRANSFORM_IN) { 319 | PropertyValuesHolder scaleHolder = PropertyValuesHolder.ofFloat("scale", mTransfrom.startScale, mTransfrom.endScale); 320 | PropertyValuesHolder leftHolder = PropertyValuesHolder.ofFloat("left", mTransfrom.startRect.left, mTransfrom.endRect.left); 321 | PropertyValuesHolder topHolder = PropertyValuesHolder.ofFloat("top", mTransfrom.startRect.top, mTransfrom.endRect.top); 322 | PropertyValuesHolder widthHolder = PropertyValuesHolder.ofFloat("width", mTransfrom.startRect.width, mTransfrom.endRect.width); 323 | PropertyValuesHolder heightHolder = PropertyValuesHolder.ofFloat("height", mTransfrom.startRect.height, mTransfrom.endRect.height); 324 | PropertyValuesHolder alphaHolder = PropertyValuesHolder.ofInt("alpha", 0, 255); 325 | valueAnimator.setValues(scaleHolder, leftHolder, topHolder, widthHolder, heightHolder, alphaHolder); 326 | } else { 327 | PropertyValuesHolder scaleHolder = PropertyValuesHolder.ofFloat("scale", mTransfrom.endScale, mTransfrom.startScale); 328 | PropertyValuesHolder leftHolder = PropertyValuesHolder.ofFloat("left", mTransfrom.endRect.left, mTransfrom.startRect.left); 329 | PropertyValuesHolder topHolder = PropertyValuesHolder.ofFloat("top", mTransfrom.endRect.top, mTransfrom.startRect.top); 330 | PropertyValuesHolder widthHolder = PropertyValuesHolder.ofFloat("width", mTransfrom.endRect.width, mTransfrom.startRect.width); 331 | PropertyValuesHolder heightHolder = PropertyValuesHolder.ofFloat("height", mTransfrom.endRect.height, mTransfrom.startRect.height); 332 | PropertyValuesHolder alphaHolder = PropertyValuesHolder.ofInt("alpha", 255, 0); 333 | valueAnimator.setValues(scaleHolder, leftHolder, topHolder, widthHolder, heightHolder, alphaHolder); 334 | } 335 | 336 | valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 337 | @Override 338 | public synchronized void onAnimationUpdate(ValueAnimator animation) { 339 | mTransfrom.scale = (Float) animation.getAnimatedValue("scale"); 340 | mTransfrom.rect.left = (Float) animation.getAnimatedValue("left"); 341 | mTransfrom.rect.top = (Float) animation.getAnimatedValue("top"); 342 | mTransfrom.rect.width = (Float) animation.getAnimatedValue("width"); 343 | mTransfrom.rect.height = (Float) animation.getAnimatedValue("height"); 344 | mBgAlpha = (Integer) animation.getAnimatedValue("alpha"); 345 | invalidate(); 346 | ((Activity)getContext()).getWindow().getDecorView().invalidate(); 347 | } 348 | }); 349 | valueAnimator.addListener(new ValueAnimator.AnimatorListener() { 350 | @Override 351 | public void onAnimationStart(Animator animation) { 352 | 353 | } 354 | 355 | @Override 356 | public void onAnimationRepeat(Animator animation) { 357 | 358 | } 359 | 360 | @Override 361 | public void onAnimationEnd(Animator animation) { 362 | /* 363 | * 如果是进入的话,当然是希望最后停留在center_crop的区域。但是如果是out的话,就不应该是center_crop的位置了 364 | * , 而应该是最后变化的位置,因为但是out的时候,不回复视图是Normal,要不然会有一个突然闪动回去的bug 365 | */ 366 | // TODO 这个可以根据实际需求来修改 367 | if (state == STATE_TRANSFORM_IN) { 368 | mState = STATE_NORMAL; 369 | } 370 | if (mTransformListener != null) { 371 | mTransformListener.onTransformComplete(state); 372 | } 373 | } 374 | 375 | @Override 376 | public void onAnimationCancel(Animator animation) { 377 | 378 | } 379 | }); 380 | valueAnimator.start(); 381 | } 382 | 383 | private final int mBgColor = 0xFF000000; 384 | private int mBgAlpha = 0; 385 | 386 | public void setOnTransformListener(TransformListener listener) { 387 | mTransformListener = listener; 388 | } 389 | 390 | private TransformListener mTransformListener; 391 | 392 | public static interface TransformListener { 393 | /** 394 | * 395 | * @param mode 396 | * STATE_TRANSFORM_IN 1 ,STATE_TRANSFORM_OUT 2 397 | */ 398 | void onTransformComplete(int mode);// mode 1 399 | } 400 | 401 | } 402 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/views/SpacesItemDecoration.java: -------------------------------------------------------------------------------- 1 | package lico.example.views; 2 | 3 | import android.graphics.Rect; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.View; 6 | 7 | /** 8 | * Created by zzk on 15/12/28. 9 | */ 10 | public class SpacesItemDecoration extends RecyclerView.ItemDecoration{ 11 | 12 | private int space; 13 | 14 | public SpacesItemDecoration(int space) { 15 | this.space = space; 16 | } 17 | 18 | @Override 19 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { 20 | outRect.left = space; 21 | outRect.right = space; 22 | outRect.bottom = space; 23 | if(parent.getChildAdapterPosition(view) == 0){ 24 | outRect.top = space; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/views/SuperRecyclerView.java: -------------------------------------------------------------------------------- 1 | package lico.example.views; 2 | 3 | import android.content.Context; 4 | import android.support.v4.widget.SwipeRefreshLayout; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.util.AttributeSet; 7 | import android.view.LayoutInflater; 8 | import android.view.MotionEvent; 9 | import android.view.View; 10 | import android.widget.LinearLayout; 11 | 12 | import lico.example.R; 13 | 14 | /** 15 | * Created by zzk on 15/12/30. 16 | */ 17 | public class SuperRecyclerView extends LinearLayout{ 18 | 19 | private RecyclerView mRecyclerView; 20 | private SwipeRefreshLayout mSwipeRefreshLayout; 21 | private PullLoadMoreListener mLoadMoreListener; 22 | private boolean isRefresh = false; 23 | private Context mContext; 24 | 25 | public SuperRecyclerView(Context context) { 26 | super(context); 27 | init(context); 28 | } 29 | 30 | public SuperRecyclerView(Context context, AttributeSet attrs) { 31 | super(context, attrs); 32 | init(context); 33 | } 34 | 35 | private void init(Context context){ 36 | mContext = context; 37 | View view = LayoutInflater.from(mContext).inflate(R.layout.view_pull_load_more, null); 38 | 39 | mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipe_refreshlayout); 40 | mSwipeRefreshLayout.setColorSchemeResources(android.R.color.holo_green_dark, android.R.color.holo_blue_dark, android.R.color.holo_orange_dark); 41 | // mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayoutOnRefresh(this)); 42 | 43 | mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view); 44 | // mRecyclerView.addOnScrollListener(new RecyclerViewOnScroll(this)); 45 | 46 | mRecyclerView.setOnTouchListener( 47 | new View.OnTouchListener() { 48 | @Override 49 | public boolean onTouch(View v, MotionEvent event) { 50 | if (isRefresh) { 51 | return true; 52 | } else { 53 | return false; 54 | } 55 | } 56 | } 57 | ); 58 | this.addView(view); 59 | } 60 | 61 | public void refresh(){ 62 | if(mLoadMoreListener != null){ 63 | mLoadMoreListener.onRefresh(); 64 | } 65 | } 66 | 67 | public void loadMore() { 68 | if (mLoadMoreListener != null) { 69 | mLoadMoreListener.onLoadMore(); 70 | 71 | } 72 | } 73 | 74 | public interface PullLoadMoreListener { 75 | public void onRefresh(); 76 | 77 | public void onLoadMore(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /app/src/main/java/lico/example/views/SwipeRefreshLayoutOnRefresh.java: -------------------------------------------------------------------------------- 1 | package lico.example.views; 2 | 3 | import android.support.v4.widget.SwipeRefreshLayout; 4 | 5 | /** 6 | * Created by zzk on 15/12/22. 7 | */ 8 | public class SwipeRefreshLayoutOnRefresh implements SwipeRefreshLayout.OnRefreshListener { 9 | PullLoadMoreRecyclerView mPullLoadMoreRecyclerView; 10 | 11 | public SwipeRefreshLayoutOnRefresh(PullLoadMoreRecyclerView pullLoadMoreRecyclerView) { 12 | this.mPullLoadMoreRecyclerView = pullLoadMoreRecyclerView; 13 | } 14 | 15 | @Override 16 | public void onRefresh() { 17 | if (!mPullLoadMoreRecyclerView.isRefresh()) { 18 | mPullLoadMoreRecyclerView.setIsRefresh(true); 19 | mPullLoadMoreRecyclerView.refresh(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /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/activated_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/selectable_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/side_nav_bar.xml: -------------------------------------------------------------------------------- 1 | 3 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 15 | 16 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_personal.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 14 | 15 | 24 | 25 | 33 | 34 | 40 | 41 | 42 | 43 | 48 | 49 | 54 | 55 | 56 | 64 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_test.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 |