Browse Source

项目初始化

詹子聪 5 years ago
commit
2cc3354981
100 changed files with 4187 additions and 0 deletions
  1. 33 0
      adapter/build.gradle
  2. 9 0
      adapter/src/main/AndroidManifest.xml
  3. 8 0
      adapter/src/main/java/com/itant/library/Placeholder.java
  4. 41 0
      adapter/src/main/java/com/itant/library/abslistview/CommonAdapter.java
  5. 98 0
      adapter/src/main/java/com/itant/library/abslistview/MultiItemTypeAdapter.java
  6. 290 0
      adapter/src/main/java/com/itant/library/abslistview/ViewHolder.java
  7. 20 0
      adapter/src/main/java/com/itant/library/abslistview/base/ItemViewDelegate.java
  8. 134 0
      adapter/src/main/java/com/itant/library/abslistview/base/ItemViewDelegateManager.java
  9. 54 0
      adapter/src/main/java/com/itant/library/recyclerview/CommonAdapter.java
  10. 132 0
      adapter/src/main/java/com/itant/library/recyclerview/MultiItemTypeAdapter.java
  11. 16 0
      adapter/src/main/java/com/itant/library/recyclerview/base/ItemViewDelegate.java
  12. 116 0
      adapter/src/main/java/com/itant/library/recyclerview/base/ItemViewDelegateManager.java
  13. 311 0
      adapter/src/main/java/com/itant/library/recyclerview/base/ViewHolder.java
  14. 55 0
      adapter/src/main/java/com/itant/library/recyclerview/utils/WrapperUtils.java
  15. 128 0
      adapter/src/main/java/com/itant/library/recyclerview/wrapper/EmptyWrapper.java
  16. 152 0
      adapter/src/main/java/com/itant/library/recyclerview/wrapper/HeaderAndFooterWrapper.java
  17. 161 0
      adapter/src/main/java/com/itant/library/recyclerview/wrapper/LoadMoreWrapper.java
  18. 13 0
      adapter/src/main/res/anim/anim_bottom_in.xml
  19. 4 0
      adapter/src/main/res/values-v21/dimen.xml
  20. 11 0
      adapter/src/main/res/values/color.xml
  21. 5 0
      adapter/src/main/res/values/dimen.xml
  22. 3 0
      adapter/src/main/res/values/strings.xml
  23. 22 0
      adapter/src/main/res/values/styles.xml
  24. 65 0
      app/build.gradle
  25. BIN
      app/commonkey
  26. 21 0
      app/proguard-rules.pro
  27. 27 0
      app/src/androidTest/java/com/itant/shibei/ExampleInstrumentedTest.java
  28. 42 0
      app/src/main/AndroidManifest.xml
  29. 32 0
      app/src/main/java/com/itant/shibei/adapter/FragmentPagerItemAdapter.java
  30. 114 0
      app/src/main/java/com/itant/shibei/adapter/GoodsAdapter.java
  31. 70 0
      app/src/main/java/com/itant/shibei/adapter/TemplateAdapter.java
  32. 60 0
      app/src/main/java/com/itant/shibei/base/BaseShiBeiActivity.java
  33. 138 0
      app/src/main/java/com/itant/shibei/bean/BeiUser.java
  34. 234 0
      app/src/main/java/com/itant/shibei/bean/GoodsBean.java
  35. 88 0
      app/src/main/java/com/itant/shibei/bean/TemplateBean.java
  36. 15 0
      app/src/main/java/com/itant/shibei/common/ConstantString.java
  37. 32 0
      app/src/main/java/com/itant/shibei/common/ConstantUrl.java
  38. 80 0
      app/src/main/java/com/itant/shibei/tool/DataTool.java
  39. 19 0
      app/src/main/java/com/itant/shibei/tool/StringTool.java
  40. 83 0
      app/src/main/java/com/itant/shibei/tool/SystemTool.java
  41. 90 0
      app/src/main/java/com/itant/shibei/ui/MainActivity.java
  42. 46 0
      app/src/main/java/com/itant/shibei/ui/MainViewModel.java
  43. 48 0
      app/src/main/java/com/itant/shibei/ui/function/FunctionFragment.java
  44. 17 0
      app/src/main/java/com/itant/shibei/ui/function/template/ITemplateView.java
  45. 61 0
      app/src/main/java/com/itant/shibei/ui/function/template/TemplateFragment.java
  46. 28 0
      app/src/main/java/com/itant/shibei/ui/function/template/TemplatePresenter.java
  47. 72 0
      app/src/main/java/com/itant/shibei/ui/home/GoodsFragment.java
  48. 25 0
      app/src/main/java/com/itant/shibei/ui/home/GoodsPresenter.java
  49. 52 0
      app/src/main/java/com/itant/shibei/ui/home/HomeFragment.java
  50. 17 0
      app/src/main/java/com/itant/shibei/ui/home/IGoodsView.java
  51. 37 0
      app/src/main/java/com/itant/shibei/ui/mine/AboutActivity.java
  52. 55 0
      app/src/main/java/com/itant/shibei/ui/mine/MineFragment.java
  53. 74 0
      app/src/main/java/com/itant/shibei/ui/mine/login/LoginActivity.java
  54. 37 0
      app/src/main/java/com/itant/shibei/ui/mine/login/UserInfoManager.java
  55. 63 0
      app/src/main/java/com/itant/shibei/ui/mine/login/forget/ForgetActivity.java
  56. 63 0
      app/src/main/java/com/itant/shibei/ui/mine/login/register/RegisterActivity.java
  57. 3 0
      app/src/main/res/anim/nav_default_enter_anim.xml
  58. 3 0
      app/src/main/res/anim/nav_default_exit_anim.xml
  59. 3 0
      app/src/main/res/anim/nav_default_pop_enter_anim.xml
  60. 3 0
      app/src/main/res/anim/nav_default_pop_exit_anim.xml
  61. 6 0
      app/src/main/res/color/selector_edittext_outline.xml
  62. 5 0
      app/src/main/res/color/selector_nav_item_color.xml
  63. 7 0
      app/src/main/res/drawable-v21/ripple_click.xml
  64. 6 0
      app/src/main/res/drawable-v21/selectable_item_background.xml
  65. 14 0
      app/src/main/res/drawable/ic_computer.xml
  66. 15 0
      app/src/main/res/drawable/ic_done.xml
  67. 10 0
      app/src/main/res/drawable/ic_launcher.xml
  68. 11 0
      app/src/main/res/drawable/ic_logo.xml
  69. 9 0
      app/src/main/res/drawable/ic_mine_about.xml
  70. 13 0
      app/src/main/res/drawable/ic_mine_cash.xml
  71. 9 0
      app/src/main/res/drawable/ic_mine_feedback.xml
  72. 9 0
      app/src/main/res/drawable/ic_mine_mall.xml
  73. 16 0
      app/src/main/res/drawable/ic_mine_money.xml
  74. 9 0
      app/src/main/res/drawable/ic_mine_star.xml
  75. 9 0
      app/src/main/res/drawable/ic_mine_update.xml
  76. 13 0
      app/src/main/res/drawable/ic_mine_upload.xml
  77. 12 0
      app/src/main/res/drawable/ic_nav_fire.xml
  78. 15 0
      app/src/main/res/drawable/ic_nav_game.xml
  79. 9 0
      app/src/main/res/drawable/ic_nav_mall.xml
  80. 9 0
      app/src/main/res/drawable/ic_nav_mine.xml
  81. 10 0
      app/src/main/res/drawable/ic_nav_template.xml
  82. 9 0
      app/src/main/res/drawable/ic_search.xml
  83. 80 0
      app/src/main/res/drawable/layer_shadow.xml
  84. 21 0
      app/src/main/res/drawable/ripple_oval.xml
  85. 5 0
      app/src/main/res/drawable/selectable_item_background.xml
  86. 22 0
      app/src/main/res/drawable/selector_btn.xml
  87. 6 0
      app/src/main/res/drawable/shape_black_radius_transparent.xml
  88. 10 0
      app/src/main/res/drawable/shape_black_stroke_right.xml
  89. 8 0
      app/src/main/res/drawable/shape_black_tag_gradient.xml
  90. 6 0
      app/src/main/res/drawable/shape_circle.xml
  91. 6 0
      app/src/main/res/drawable/shape_gray_stroke_s.xml
  92. 7 0
      app/src/main/res/drawable/shape_gray_stroke_s_radius.xml
  93. 6 0
      app/src/main/res/drawable/shape_gray_stroke_solid.xml
  94. 10 0
      app/src/main/res/drawable/shape_gray_tag.xml
  95. 10 0
      app/src/main/res/drawable/shape_purple_stroke_right.xml
  96. 9 0
      app/src/main/res/drawable/shape_purple_tag_gradient.xml
  97. 7 0
      app/src/main/res/drawable/shape_radius.xml
  98. 8 0
      app/src/main/res/drawable/shape_red_tag_gradient.xml
  99. 8 0
      app/src/main/res/drawable/shape_shadow.xml
  100. 0 0
      app/src/main/res/layout/activity_about.xml

+ 33 - 0
adapter/build.gradle

@@ -0,0 +1,33 @@
+apply plugin: 'com.android.library'
+
+android {
+    compileSdkVersion versions.compileSdk
+    buildToolsVersion versions.buildTools
+
+    defaultConfig {
+        minSdkVersion versions.minSdk
+        targetSdkVersion versions.targetSdk
+        versionCode 1
+        versionName "1.0"
+
+        //testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+
+    }
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+    }
+}
+
+dependencies {
+    compile fileTree(dir: 'libs', include: ['*.jar'])
+    /*androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
+        exclude group: 'com.android.support', module: 'support-annotations'
+    })
+    testCompile 'junit:junit:4.12'*/
+
+    api 'androidx.appcompat:appcompat:1.3.0-alpha01'
+    api 'com.google.android.material:material:1.1.0'
+}

+ 9 - 0
adapter/src/main/AndroidManifest.xml

@@ -0,0 +1,9 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.itant.library">
+
+    <application  android:label="@string/app_name">
+        <!--android:allowBackup="true"
+        android:supportsRtl="true"-->
+
+    </application>
+
+</manifest>

+ 8 - 0
adapter/src/main/java/com/itant/library/Placeholder.java

@@ -0,0 +1,8 @@
+package com.itant.library;
+
+/**
+ * Created by iTant on 2017/3/27.
+ */
+
+public class Placeholder {
+}

+ 41 - 0
adapter/src/main/java/com/itant/library/abslistview/CommonAdapter.java

@@ -0,0 +1,41 @@
+package com.itant.library.abslistview;
+
+import android.content.Context;
+
+
+import com.itant.library.abslistview.base.ItemViewDelegate;
+
+import java.util.List;
+
+public abstract class CommonAdapter<T> extends MultiItemTypeAdapter<T>
+{
+
+    public CommonAdapter(Context context, final int layoutId, List<T> datas)
+    {
+        super(context, datas);
+
+        addItemViewDelegate(new ItemViewDelegate<T>()
+        {
+            @Override
+            public int getItemViewLayoutId()
+            {
+                return layoutId;
+            }
+
+            @Override
+            public boolean isForViewType(T item, int position)
+            {
+                return true;
+            }
+
+            @Override
+            public void convert(ViewHolder holder, T t, int position)
+            {
+                CommonAdapter.this.convert(holder, t, position);
+            }
+        });
+    }
+
+    protected abstract void convert(ViewHolder viewHolder, T item, int position);
+
+}

+ 98 - 0
adapter/src/main/java/com/itant/library/abslistview/MultiItemTypeAdapter.java

@@ -0,0 +1,98 @@
+package com.itant.library.abslistview;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+
+import com.itant.library.abslistview.base.ItemViewDelegate;
+import com.itant.library.abslistview.base.ItemViewDelegateManager;
+
+import java.util.List;
+
+public class MultiItemTypeAdapter<T> extends BaseAdapter {
+    protected Context mContext;
+    protected List<T> mDatas;
+
+    private ItemViewDelegateManager mItemViewDelegateManager;
+
+
+    public MultiItemTypeAdapter(Context context, List<T> datas) {
+        this.mContext = context;
+        this.mDatas = datas;
+        mItemViewDelegateManager = new ItemViewDelegateManager();
+    }
+
+    public MultiItemTypeAdapter addItemViewDelegate(ItemViewDelegate<T> itemViewDelegate) {
+        mItemViewDelegateManager.addDelegate(itemViewDelegate);
+        return this;
+    }
+
+    private boolean useItemViewDelegateManager() {
+        return mItemViewDelegateManager.getItemViewDelegateCount() > 0;
+    }
+
+    @Override
+    public int getViewTypeCount() {
+        if (useItemViewDelegateManager())
+            return mItemViewDelegateManager.getItemViewDelegateCount();
+        return super.getViewTypeCount();
+    }
+
+    @Override
+    public int getItemViewType(int position) {
+        if (useItemViewDelegateManager()) {
+            int viewType = mItemViewDelegateManager.getItemViewType(mDatas.get(position), position);
+            return viewType;
+        }
+        return super.getItemViewType(position);
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+        ItemViewDelegate itemViewDelegate = mItemViewDelegateManager.getItemViewDelegate(mDatas.get(position), position);
+        int layoutId = itemViewDelegate.getItemViewLayoutId();
+        ViewHolder viewHolder = null ;
+        if (convertView == null)
+        {
+            View itemView = LayoutInflater.from(mContext).inflate(layoutId, parent,
+                    false);
+            viewHolder = new ViewHolder(mContext, itemView, parent, position);
+            viewHolder.mLayoutId = layoutId;
+            onViewHolderCreated(viewHolder,viewHolder.getConvertView());
+        } else
+        {
+            viewHolder = (ViewHolder) convertView.getTag();
+            viewHolder.mPosition = position;
+        }
+
+
+        convert(viewHolder, getItem(position), position);
+        return viewHolder.getConvertView();
+    }
+
+    protected void convert(ViewHolder viewHolder, T item, int position) {
+        mItemViewDelegateManager.convert(viewHolder, item, position);
+    }
+
+    public void onViewHolderCreated(ViewHolder holder , View itemView )
+    {}
+
+    @Override
+    public int getCount() {
+        return mDatas.size();
+    }
+
+    @Override
+    public T getItem(int position) {
+        return mDatas.get(position);
+    }
+
+    @Override
+    public long getItemId(int position) {
+        return position;
+    }
+
+
+}

+ 290 - 0
adapter/src/main/java/com/itant/library/abslistview/ViewHolder.java

@@ -0,0 +1,290 @@
+package com.itant.library.abslistview;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Paint;
+import android.graphics.Typeface;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.text.util.Linkify;
+import android.util.SparseArray;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.AlphaAnimation;
+import android.widget.Checkable;
+import android.widget.ImageView;
+import android.widget.ProgressBar;
+import android.widget.RatingBar;
+import android.widget.TextView;
+
+public class ViewHolder
+{
+    private SparseArray<View> mViews;
+    protected int mPosition;
+    private View mConvertView;
+    private Context mContext;
+    protected int mLayoutId;
+
+    public ViewHolder(Context context, View itemView, ViewGroup parent, int position)
+    {
+        mContext = context;
+        mConvertView = itemView;
+        mPosition = position;
+        mViews = new SparseArray<View>();
+        mConvertView.setTag(this);
+    }
+
+
+    public static ViewHolder get(Context context, View convertView,
+                                 ViewGroup parent, int layoutId, int position)
+    {
+        if (convertView == null)
+        {
+            View itemView = LayoutInflater.from(context).inflate(layoutId, parent,
+                    false);
+            ViewHolder holder = new ViewHolder(context, itemView, parent, position);
+            holder.mLayoutId = layoutId;
+            return holder;
+        } else
+        {
+            ViewHolder holder = (ViewHolder) convertView.getTag();
+            holder.mPosition = position;
+            return holder;
+        }
+    }
+
+
+    /**
+     * 通过viewId获取控件
+     *
+     * @param viewId
+     * @return
+     */
+    public <T extends View> T getView(int viewId)
+    {
+        View view = mViews.get(viewId);
+        if (view == null)
+        {
+            view = mConvertView.findViewById(viewId);
+            mViews.put(viewId, view);
+        }
+        return (T) view;
+    }
+
+    public View getConvertView()
+    {
+        return mConvertView;
+    }
+
+    public int getLayoutId()
+    {
+        return mLayoutId;
+    }
+
+    public void updatePosition(int position)
+    {
+        mPosition = position;
+    }
+
+    public int getItemPosition()
+    {
+        return mPosition;
+    }
+
+
+    /****以下为辅助方法*****/
+
+    /**
+     * 设置TextView的值
+     *
+     * @param viewId
+     * @param text
+     * @return
+     */
+    public ViewHolder setText(int viewId, String text)
+    {
+        TextView tv = getView(viewId);
+        tv.setText(text);
+        return this;
+    }
+
+    public ViewHolder setImageResource(int viewId, int resId)
+    {
+        ImageView view = getView(viewId);
+        view.setImageResource(resId);
+        return this;
+    }
+
+    public ViewHolder setImageBitmap(int viewId, Bitmap bitmap)
+    {
+        ImageView view = getView(viewId);
+        view.setImageBitmap(bitmap);
+        return this;
+    }
+
+    public ViewHolder setImageDrawable(int viewId, Drawable drawable)
+    {
+        ImageView view = getView(viewId);
+        view.setImageDrawable(drawable);
+        return this;
+    }
+
+    public ViewHolder setBackgroundColor(int viewId, int color)
+    {
+        View view = getView(viewId);
+        view.setBackgroundColor(color);
+        return this;
+    }
+
+    public ViewHolder setBackgroundRes(int viewId, int backgroundRes)
+    {
+        View view = getView(viewId);
+        view.setBackgroundResource(backgroundRes);
+        return this;
+    }
+
+    public ViewHolder setTextColor(int viewId, int textColor)
+    {
+        TextView view = getView(viewId);
+        view.setTextColor(textColor);
+        return this;
+    }
+
+    public ViewHolder setTextColorRes(int viewId, int textColorRes)
+    {
+        TextView view = getView(viewId);
+        view.setTextColor(mContext.getResources().getColor(textColorRes));
+        return this;
+    }
+
+    @SuppressLint("NewApi")
+    public ViewHolder setAlpha(int viewId, float value)
+    {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
+        {
+            getView(viewId).setAlpha(value);
+        } else
+        {
+            // Pre-honeycomb hack to set Alpha value
+            AlphaAnimation alpha = new AlphaAnimation(value, value);
+            alpha.setDuration(0);
+            alpha.setFillAfter(true);
+            getView(viewId).startAnimation(alpha);
+        }
+        return this;
+    }
+
+    public ViewHolder setVisible(int viewId, boolean visible)
+    {
+        View view = getView(viewId);
+        view.setVisibility(visible ? View.VISIBLE : View.GONE);
+        return this;
+    }
+
+    public ViewHolder linkify(int viewId)
+    {
+        TextView view = getView(viewId);
+        Linkify.addLinks(view, Linkify.ALL);
+        return this;
+    }
+
+    public ViewHolder setTypeface(Typeface typeface, int... viewIds)
+    {
+        for (int viewId : viewIds)
+        {
+            TextView view = getView(viewId);
+            view.setTypeface(typeface);
+            view.setPaintFlags(view.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG);
+        }
+        return this;
+    }
+
+    public ViewHolder setProgress(int viewId, int progress)
+    {
+        ProgressBar view = getView(viewId);
+        view.setProgress(progress);
+        return this;
+    }
+
+    public ViewHolder setProgress(int viewId, int progress, int max)
+    {
+        ProgressBar view = getView(viewId);
+        view.setMax(max);
+        view.setProgress(progress);
+        return this;
+    }
+
+    public ViewHolder setMax(int viewId, int max)
+    {
+        ProgressBar view = getView(viewId);
+        view.setMax(max);
+        return this;
+    }
+
+    public ViewHolder setRating(int viewId, float rating)
+    {
+        RatingBar view = getView(viewId);
+        view.setRating(rating);
+        return this;
+    }
+
+    public ViewHolder setRating(int viewId, float rating, int max)
+    {
+        RatingBar view = getView(viewId);
+        view.setMax(max);
+        view.setRating(rating);
+        return this;
+    }
+
+    public ViewHolder setTag(int viewId, Object tag)
+    {
+        View view = getView(viewId);
+        view.setTag(tag);
+        return this;
+    }
+
+    public ViewHolder setTag(int viewId, int key, Object tag)
+    {
+        View view = getView(viewId);
+        view.setTag(key, tag);
+        return this;
+    }
+
+    public ViewHolder setChecked(int viewId, boolean checked)
+    {
+        Checkable view = (Checkable) getView(viewId);
+        view.setChecked(checked);
+        return this;
+    }
+
+    /**
+     * 关于事件的
+     */
+    public ViewHolder setOnClickListener(int viewId,
+                                         View.OnClickListener listener)
+    {
+        View view = getView(viewId);
+        view.setOnClickListener(listener);
+        return this;
+    }
+
+    public ViewHolder setOnTouchListener(int viewId,
+                                         View.OnTouchListener listener)
+    {
+        View view = getView(viewId);
+        view.setOnTouchListener(listener);
+        return this;
+    }
+
+    public ViewHolder setOnLongClickListener(int viewId,
+                                             View.OnLongClickListener listener)
+    {
+        View view = getView(viewId);
+        view.setOnLongClickListener(listener);
+        return this;
+    }
+
+
+}

+ 20 - 0
adapter/src/main/java/com/itant/library/abslistview/base/ItemViewDelegate.java

@@ -0,0 +1,20 @@
+package com.itant.library.abslistview.base;
+
+
+import com.itant.library.abslistview.ViewHolder;
+
+/**
+ * Created by iTant on 2017/1/15.
+ */
+public interface ItemViewDelegate<T>
+{
+
+    public abstract int getItemViewLayoutId();
+
+    public abstract boolean isForViewType(T item, int position);
+
+    public abstract void convert(ViewHolder holder, T t, int position);
+
+
+
+}

+ 134 - 0
adapter/src/main/java/com/itant/library/abslistview/base/ItemViewDelegateManager.java

@@ -0,0 +1,134 @@
+package com.itant.library.abslistview.base;
+
+
+import androidx.collection.SparseArrayCompat;
+
+import com.itant.library.abslistview.ViewHolder;
+
+
+/**
+ * Created by iTant on 2017/1/15.
+ */
+public class ItemViewDelegateManager<T>
+{
+    SparseArrayCompat<ItemViewDelegate<T>> delegates = new SparseArrayCompat();
+
+    public int getItemViewDelegateCount()
+    {
+        return delegates.size();
+    }
+
+    public ItemViewDelegateManager<T> addDelegate(ItemViewDelegate<T> delegate)
+    {
+        int viewType = delegates.size();
+        if (delegate != null)
+        {
+            delegates.put(viewType, delegate);
+            viewType++;
+        }
+        return this;
+    }
+
+    public ItemViewDelegateManager<T> addDelegate(int viewType, ItemViewDelegate<T> delegate)
+    {
+        if (delegates.get(viewType) != null)
+        {
+            throw new IllegalArgumentException(
+                    "An ItemViewDelegate is already registered for the viewType = "
+                            + viewType
+                            + ". Already registered ItemViewDelegate is "
+                            + delegates.get(viewType));
+        }
+        delegates.put(viewType, delegate);
+        return this;
+    }
+
+    public ItemViewDelegateManager<T> removeDelegate(ItemViewDelegate<T> delegate)
+    {
+        if (delegate == null)
+        {
+            throw new NullPointerException("ItemViewDelegate is null");
+        }
+        int indexToRemove = delegates.indexOfValue(delegate);
+
+        if (indexToRemove >= 0)
+        {
+            delegates.removeAt(indexToRemove);
+        }
+        return this;
+    }
+
+    public ItemViewDelegateManager<T> removeDelegate(int itemType)
+    {
+        int indexToRemove = delegates.indexOfKey(itemType);
+
+        if (indexToRemove >= 0)
+        {
+            delegates.removeAt(indexToRemove);
+        }
+        return this;
+    }
+
+    public int getItemViewType(T item, int position)
+    {
+        int delegatesCount = delegates.size();
+        for (int i = delegatesCount - 1; i >= 0; i--)
+        {
+            ItemViewDelegate<T> delegate = delegates.valueAt(i);
+            if (delegate.isForViewType(item, position))
+            {
+                return delegates.keyAt(i);
+            }
+        }
+        throw new IllegalArgumentException(
+                "No ItemViewDelegate added that matches position=" + position + " in data source");
+    }
+
+    public void convert(ViewHolder holder, T item, int position)
+    {
+        int delegatesCount = delegates.size();
+        for (int i = 0; i < delegatesCount; i++)
+        {
+            ItemViewDelegate<T> delegate = delegates.valueAt(i);
+
+            if (delegate.isForViewType(item, position))
+            {
+                delegate.convert(holder, item, position);
+                return;
+            }
+        }
+        throw new IllegalArgumentException(
+                "No ItemViewDelegateManager added that matches position=" + position + " in data source");
+    }
+
+
+    public int getItemViewLayoutId(int viewType)
+    {
+        return delegates.get(viewType).getItemViewLayoutId();
+    }
+
+    public int getItemViewType(ItemViewDelegate itemViewDelegate)
+    {
+        return delegates.indexOfValue(itemViewDelegate);
+    }
+
+    public ItemViewDelegate getItemViewDelegate(T item, int position)
+    {
+        int delegatesCount = delegates.size();
+        for (int i = delegatesCount - 1; i >= 0; i--)
+        {
+            ItemViewDelegate<T> delegate = delegates.valueAt(i);
+            if (delegate.isForViewType(item, position))
+            {
+                return delegate;
+            }
+        }
+        throw new IllegalArgumentException(
+                "No ItemViewDelegate added that matches position=" + position + " in data source");
+    }
+
+    public int getItemViewLayoutId(T item, int position)
+    {
+        return getItemViewDelegate(item,position).getItemViewLayoutId();
+    }
+}

+ 54 - 0
adapter/src/main/java/com/itant/library/recyclerview/CommonAdapter.java

@@ -0,0 +1,54 @@
+package com.itant.library.recyclerview;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+
+import com.itant.library.recyclerview.base.ItemViewDelegate;
+import com.itant.library.recyclerview.base.ViewHolder;
+
+import java.util.List;
+
+/**
+ * Created by iTant on 2017/1/15.
+ */
+public abstract class CommonAdapter<T> extends MultiItemTypeAdapter<T>
+{
+    protected Context mContext;
+    protected int mLayoutId;
+    protected List<T> mDatas;
+    protected LayoutInflater mInflater;
+
+    public CommonAdapter(final Context context, final int layoutId, List<T> datas)
+    {
+        super(context, datas);
+        mContext = context;
+        mInflater = LayoutInflater.from(context);
+        mLayoutId = layoutId;
+        mDatas = datas;
+
+        addItemViewDelegate(new ItemViewDelegate<T>()
+        {
+            @Override
+            public int getItemViewLayoutId()
+            {
+                return layoutId;
+            }
+
+            @Override
+            public boolean isForViewType( T item, int position)
+            {
+                return true;
+            }
+
+            @Override
+            public void convert(ViewHolder holder, T t, int position)
+            {
+                CommonAdapter.this.convert(holder, t, position);
+            }
+        });
+    }
+
+    protected abstract void convert(ViewHolder holder, T t, int position);
+
+
+}

+ 132 - 0
adapter/src/main/java/com/itant/library/recyclerview/MultiItemTypeAdapter.java

@@ -0,0 +1,132 @@
+package com.itant.library.recyclerview;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.itant.library.recyclerview.base.ItemViewDelegate;
+import com.itant.library.recyclerview.base.ItemViewDelegateManager;
+import com.itant.library.recyclerview.base.ViewHolder;
+
+import java.util.List;
+
+/**
+ * Created by iTant on 2017/1/15.
+ */
+public class MultiItemTypeAdapter<T> extends RecyclerView.Adapter<ViewHolder> {
+    protected Context mContext;
+    protected List<T> mDatas;
+
+    protected ItemViewDelegateManager mItemViewDelegateManager;
+    protected OnItemClickListener mOnItemClickListener;
+
+
+    public MultiItemTypeAdapter(Context context, List<T> datas) {
+        mContext = context;
+        mDatas = datas;
+        mItemViewDelegateManager = new ItemViewDelegateManager();
+    }
+
+    @Override
+    public int getItemViewType(int position) {
+        if (!useItemViewDelegateManager()) return super.getItemViewType(position);
+        return mItemViewDelegateManager.getItemViewType(mDatas.get(position), position);
+    }
+
+
+    @Override
+    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+        ItemViewDelegate itemViewDelegate = mItemViewDelegateManager.getItemViewDelegate(viewType);
+        int layoutId = itemViewDelegate.getItemViewLayoutId();
+        ViewHolder holder = ViewHolder.createViewHolder(mContext, parent, layoutId);
+        onViewHolderCreated(holder,holder.getConvertView());
+        setListener(parent, holder, viewType);
+        return holder;
+    }
+
+    public void onViewHolderCreated(ViewHolder holder,View itemView){
+
+    }
+
+    public void convert(ViewHolder holder, T t) {
+        mItemViewDelegateManager.convert(holder, t, holder.getAdapterPosition());
+    }
+
+    protected boolean isEnabled(int viewType) {
+        return true;
+    }
+
+
+    protected void setListener(final ViewGroup parent, final ViewHolder viewHolder, int viewType) {
+        if (!isEnabled(viewType)) return;
+        viewHolder.getConvertView().setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (mOnItemClickListener != null) {
+                    int position = viewHolder.getAdapterPosition();
+                    mOnItemClickListener.onItemClick(v, viewHolder , position);
+                }
+            }
+        });
+
+        viewHolder.getConvertView().setOnLongClickListener(new View.OnLongClickListener() {
+            @Override
+            public boolean onLongClick(View v) {
+                if (mOnItemClickListener != null) {
+                    int position = viewHolder.getAdapterPosition();
+                    return mOnItemClickListener.onItemLongClick(v, viewHolder, position);
+                }
+                return false;
+            }
+        });
+    }
+
+    private int mLastPosition=-1;// 设为-1是为了让动画从第0个item出现
+    @Override
+    public void onBindViewHolder(ViewHolder holder, int position) {
+        convert(holder, mDatas.get(position));
+        /*if (position > mLastPosition && !isFooterPosition(position)) {
+            // 一个一个出现的动画
+            Animation animation = AnimationUtils.loadAnimation(holder.itemView.getContext(), R.anim.anim_bottom_in);
+            holder.itemView.startAnimation(animation);
+            mLastPosition = position;
+        }*/
+    }
+
+    @Override
+    public int getItemCount() {
+        int itemCount = mDatas.size();
+        return itemCount;
+    }
+
+
+    public List<T> getDatas() {
+        return mDatas;
+    }
+
+    public MultiItemTypeAdapter addItemViewDelegate(ItemViewDelegate<T> itemViewDelegate) {
+        mItemViewDelegateManager.addDelegate(itemViewDelegate);
+        return this;
+    }
+
+    public MultiItemTypeAdapter addItemViewDelegate(int viewType, ItemViewDelegate<T> itemViewDelegate) {
+        mItemViewDelegateManager.addDelegate(viewType, itemViewDelegate);
+        return this;
+    }
+
+    protected boolean useItemViewDelegateManager() {
+        return mItemViewDelegateManager.getItemViewDelegateCount() > 0;
+    }
+
+    public interface OnItemClickListener {
+        void onItemClick(View view, RecyclerView.ViewHolder holder, int position);
+
+        boolean onItemLongClick(View view, RecyclerView.ViewHolder holder, int position);
+    }
+
+    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
+        this.mOnItemClickListener = onItemClickListener;
+    }
+}

+ 16 - 0
adapter/src/main/java/com/itant/library/recyclerview/base/ItemViewDelegate.java

@@ -0,0 +1,16 @@
+package com.itant.library.recyclerview.base;
+
+
+/**
+ * Created by iTant on 2017/1/15.
+ */
+public interface ItemViewDelegate<T>
+{
+
+    int getItemViewLayoutId();
+
+    boolean isForViewType(T item, int position);
+
+    void convert(ViewHolder holder, T t, int position);
+
+}

+ 116 - 0
adapter/src/main/java/com/itant/library/recyclerview/base/ItemViewDelegateManager.java

@@ -0,0 +1,116 @@
+package com.itant.library.recyclerview.base;
+
+
+import androidx.collection.SparseArrayCompat;
+
+/**
+ * Created by iTant on 2017/1/15.
+ */
+public class ItemViewDelegateManager<T>
+{
+    SparseArrayCompat<ItemViewDelegate<T>> delegates = new SparseArrayCompat();
+
+    public int getItemViewDelegateCount()
+    {
+        return delegates.size();
+    }
+
+    public ItemViewDelegateManager<T> addDelegate(ItemViewDelegate<T> delegate)
+    {
+        int viewType = delegates.size();
+        if (delegate != null)
+        {
+            delegates.put(viewType, delegate);
+            viewType++;
+        }
+        return this;
+    }
+
+    public ItemViewDelegateManager<T> addDelegate(int viewType, ItemViewDelegate<T> delegate)
+    {
+        if (delegates.get(viewType) != null)
+        {
+            throw new IllegalArgumentException(
+                    "An ItemViewDelegate is already registered for the viewType = "
+                            + viewType
+                            + ". Already registered ItemViewDelegate is "
+                            + delegates.get(viewType));
+        }
+        delegates.put(viewType, delegate);
+        return this;
+    }
+
+    public ItemViewDelegateManager<T> removeDelegate(ItemViewDelegate<T> delegate)
+    {
+        if (delegate == null)
+        {
+            throw new NullPointerException("ItemViewDelegate is null");
+        }
+        int indexToRemove = delegates.indexOfValue(delegate);
+
+        if (indexToRemove >= 0)
+        {
+            delegates.removeAt(indexToRemove);
+        }
+        return this;
+    }
+
+    public ItemViewDelegateManager<T> removeDelegate(int itemType)
+    {
+        int indexToRemove = delegates.indexOfKey(itemType);
+
+        if (indexToRemove >= 0)
+        {
+            delegates.removeAt(indexToRemove);
+        }
+        return this;
+    }
+
+    public int getItemViewType(T item, int position)
+    {
+        int delegatesCount = delegates.size();
+        for (int i = delegatesCount - 1; i >= 0; i--)
+        {
+            ItemViewDelegate<T> delegate = delegates.valueAt(i);
+            if (delegate.isForViewType( item, position))
+            {
+                return delegates.keyAt(i);
+            }
+        }
+        throw new IllegalArgumentException(
+                "No ItemViewDelegate added that matches position=" + position + " in data source");
+    }
+
+    public void convert(ViewHolder holder, T item, int position)
+    {
+        int delegatesCount = delegates.size();
+        for (int i = 0; i < delegatesCount; i++)
+        {
+            ItemViewDelegate<T> delegate = delegates.valueAt(i);
+
+            if (delegate.isForViewType( item, position))
+            {
+                delegate.convert(holder, item, position);
+                return;
+            }
+        }
+        throw new IllegalArgumentException(
+                "No ItemViewDelegateManager added that matches position=" + position + " in data source");
+    }
+
+
+    public ItemViewDelegate getItemViewDelegate(int viewType)
+    {
+        return delegates.get(viewType);
+    }
+
+    public int getItemViewLayoutId(int viewType)
+    {
+        return getItemViewDelegate(viewType).getItemViewLayoutId();
+    }
+
+    public int getItemViewType(ItemViewDelegate itemViewDelegate)
+    {
+        return delegates.indexOfValue(itemViewDelegate);
+    }
+}

+ 311 - 0
adapter/src/main/java/com/itant/library/recyclerview/base/ViewHolder.java

@@ -0,0 +1,311 @@
+package com.itant.library.recyclerview.base;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.Typeface;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
+import android.os.Build;
+import android.text.util.Linkify;
+import android.util.SparseArray;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.AlphaAnimation;
+import android.widget.Checkable;
+import android.widget.ImageView;
+import android.widget.ProgressBar;
+import android.widget.RatingBar;
+import android.widget.TextView;
+
+import androidx.recyclerview.widget.RecyclerView;
+
+public class ViewHolder extends RecyclerView.ViewHolder/* implements AnimateViewHolder*/
+{
+    private SparseArray<View> mViews;
+    private View mConvertView;
+    private Context mContext;
+
+    public ViewHolder(Context context, View itemView)
+    {
+        super(itemView);
+        mContext = context;
+        mConvertView = itemView;
+        mViews = new SparseArray<View>();
+    }
+
+
+    public static ViewHolder createViewHolder(Context context, View itemView)
+    {
+        ViewHolder holder = new ViewHolder(context, itemView);
+        return holder;
+    }
+
+    public static ViewHolder createViewHolder(Context context,
+                                              ViewGroup parent, int layoutId)
+    {
+        View itemView = LayoutInflater.from(context).inflate(layoutId, parent,
+                false);
+        ViewHolder holder = new ViewHolder(context, itemView);
+        return holder;
+    }
+
+    /**
+     * 通过viewId获取控件
+     *
+     * @param viewId
+     * @return
+     */
+    public <T extends View> T getView(int viewId)
+    {
+        View view = mViews.get(viewId);
+        if (view == null)
+        {
+            view = mConvertView.findViewById(viewId);
+            mViews.put(viewId, view);
+        }
+        return (T) view;
+    }
+
+    public View getConvertView()
+    {
+        return mConvertView;
+    }
+
+
+
+
+    /****以下为辅助方法*****/
+
+    /**
+     * 设置TextView的值
+     *
+     * @param viewId
+     * @param text
+     * @return
+     */
+    public ViewHolder setText(int viewId, String text)
+    {
+        TextView tv = getView(viewId);
+        tv.setText(text);
+        return this;
+    }
+
+    public ViewHolder setImageResource(int viewId, int resId)
+    {
+        ImageView view = getView(viewId);
+        view.setImageResource(resId);
+        return this;
+    }
+
+    public ViewHolder setImageBitmap(int viewId, Bitmap bitmap)
+    {
+        ImageView view = getView(viewId);
+        view.setImageBitmap(bitmap);
+        return this;
+    }
+
+    public ViewHolder setImageDrawable(int viewId, Drawable drawable)
+    {
+        ImageView view = getView(viewId);
+        view.setImageDrawable(drawable);
+        return this;
+    }
+
+    public ViewHolder setBackgroundColor(int viewId, int color)
+    {
+        View view = getView(viewId);
+        view.setBackgroundColor(color);
+        return this;
+    }
+
+    public ViewHolder setBackgroundRes(int viewId, int backgroundRes)
+    {
+        View view = getView(viewId);
+        view.setBackgroundResource(backgroundRes);
+        return this;
+    }
+
+    public ViewHolder setTextColor(int viewId, int textColor)
+    {
+        TextView view = getView(viewId);
+        view.setTextColor(textColor);
+        return this;
+    }
+
+    public ViewHolder setTextColorRes(int viewId, int textColorRes)
+    {
+        TextView view = getView(viewId);
+        view.setTextColor(mContext.getResources().getColor(textColorRes));
+        return this;
+    }
+
+    @SuppressLint("NewApi")
+    public ViewHolder setAlpha(int viewId, float value)
+    {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
+        {
+            getView(viewId).setAlpha(value);
+        } else
+        {
+            // Pre-honeycomb hack to set Alpha value
+            AlphaAnimation alpha = new AlphaAnimation(value, value);
+            alpha.setDuration(0);
+            alpha.setFillAfter(true);
+            getView(viewId).startAnimation(alpha);
+        }
+        return this;
+    }
+
+    public ViewHolder setVisible(int viewId, boolean visible)
+    {
+        View view = getView(viewId);
+        view.setVisibility(visible ? View.VISIBLE : View.GONE);
+        return this;
+    }
+
+    public ViewHolder linkify(int viewId)
+    {
+        TextView view = getView(viewId);
+        Linkify.addLinks(view, Linkify.ALL);
+        return this;
+    }
+
+    public ViewHolder setTypeface(Typeface typeface, int... viewIds)
+    {
+        for (int viewId : viewIds)
+        {
+            TextView view = getView(viewId);
+            view.setTypeface(typeface);
+            view.setPaintFlags(view.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG);
+        }
+        return this;
+    }
+
+    public ViewHolder setProgress(int viewId, int progress)
+    {
+        ProgressBar view = getView(viewId);
+        view.setProgress(progress);
+        return this;
+    }
+
+    public ViewHolder setProgress(int viewId, int progress, int max)
+    {
+        ProgressBar view = getView(viewId);
+        view.setMax(max);
+        view.setProgress(progress);
+        return this;
+    }
+
+    public ViewHolder setMax(int viewId, int max)
+    {
+        ProgressBar view = getView(viewId);
+        view.setMax(max);
+        return this;
+    }
+
+    public ViewHolder setRating(int viewId, float rating)
+    {
+        RatingBar view = getView(viewId);
+        LayerDrawable stars = (LayerDrawable) view.getProgressDrawable();
+        stars.getDrawable(2).setColorFilter(Color.parseColor("#eb002f"), PorterDuff.Mode.SRC_ATOP);
+        view.setRating(rating);
+        return this;
+    }
+
+    public ViewHolder setRating(int viewId, float rating, int max)
+    {
+        RatingBar view = getView(viewId);
+        view.setMax(max);
+        view.setRating(rating);
+        return this;
+    }
+
+    public ViewHolder setTag(int viewId, Object tag)
+    {
+        View view = getView(viewId);
+        view.setTag(tag);
+        return this;
+    }
+
+    public ViewHolder setTag(int viewId, int key, Object tag)
+    {
+        View view = getView(viewId);
+        view.setTag(key, tag);
+        return this;
+    }
+
+    public ViewHolder setChecked(int viewId, boolean checked)
+    {
+        Checkable view = (Checkable) getView(viewId);
+        view.setChecked(checked);
+        return this;
+    }
+
+    /**
+     * 关于事件的
+     */
+    public ViewHolder setOnClickListener(int viewId,
+                                         View.OnClickListener listener)
+    {
+        View view = getView(viewId);
+        view.setOnClickListener(listener);
+        return this;
+    }
+
+    public ViewHolder setOnTouchListener(int viewId,
+                                         View.OnTouchListener listener)
+    {
+        View view = getView(viewId);
+        view.setOnTouchListener(listener);
+        return this;
+    }
+
+    public ViewHolder setOnLongClickListener(int viewId,
+                                             View.OnLongClickListener listener)
+    {
+        View view = getView(viewId);
+        view.setOnLongClickListener(listener);
+        return this;
+    }
+
+
+    /*----------------------------------动画----------------------------------*/
+    /*@Override
+    public void preAnimateAddImpl(RecyclerView.ViewHolder holder) {
+        ViewCompat.setTranslationY(itemView, -itemView.getHeight() * 0.3f);
+        ViewCompat.setAlpha(itemView, 0);
+    }
+
+    @Override
+    public void preAnimateRemoveImpl(RecyclerView.ViewHolder holder) {
+
+    }
+
+    @Override
+    public void animateAddImpl(RecyclerView.ViewHolder holder, ViewPropertyAnimatorListener listener) {
+        // 添加的动画
+        ViewCompat.animate(itemView)
+                .translationY(0)
+                .alpha(1)
+                .setDuration(300)
+                .setListener(listener)
+                .start();
+    }
+
+    @Override
+    public void animateRemoveImpl(RecyclerView.ViewHolder holder, ViewPropertyAnimatorListener listener) {
+        // 移除的动画
+        ViewCompat.animate(itemView)
+                .translationY(-itemView.getHeight() * 0.3f)
+                .alpha(0)
+                .setDuration(300)
+                .setListener(listener)
+                .start();
+    }*/
+    /*----------------------------------动画----------------------------------*/
+}

+ 55 - 0
adapter/src/main/java/com/itant/library/recyclerview/utils/WrapperUtils.java

@@ -0,0 +1,55 @@
+package com.itant.library.recyclerview.utils;
+
+
+import android.view.ViewGroup;
+
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.StaggeredGridLayoutManager;
+
+/**
+ * Created by iTant on 2017/1/15.
+ */
+public class WrapperUtils
+{
+    public interface SpanSizeCallback
+    {
+        int getSpanSize(GridLayoutManager layoutManager, GridLayoutManager.SpanSizeLookup oldLookup, int position);
+    }
+
+    public static void onAttachedToRecyclerView(RecyclerView.Adapter innerAdapter, RecyclerView recyclerView, final SpanSizeCallback callback)
+    {
+        innerAdapter.onAttachedToRecyclerView(recyclerView);
+
+        RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
+        if (layoutManager instanceof GridLayoutManager)
+        {
+            final GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
+            final GridLayoutManager.SpanSizeLookup spanSizeLookup = gridLayoutManager.getSpanSizeLookup();
+
+            gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup()
+            {
+                @Override
+                public int getSpanSize(int position)
+                {
+                    return callback.getSpanSize(gridLayoutManager, spanSizeLookup, position);
+                }
+            });
+            gridLayoutManager.setSpanCount(gridLayoutManager.getSpanCount());
+        }
+    }
+
+    public static void setFullSpan(RecyclerView.ViewHolder holder)
+    {
+        ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
+
+        if (lp != null
+                && lp instanceof StaggeredGridLayoutManager.LayoutParams)
+        {
+
+            StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp;
+
+            p.setFullSpan(true);
+        }
+    }
+}

+ 128 - 0
adapter/src/main/java/com/itant/library/recyclerview/wrapper/EmptyWrapper.java

@@ -0,0 +1,128 @@
+package com.itant.library.recyclerview.wrapper;
+
+
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.itant.library.recyclerview.base.ViewHolder;
+import com.itant.library.recyclerview.utils.WrapperUtils;
+
+/**
+ * Created by iTant on 2017/1/15.
+ */
+public class EmptyWrapper<T> extends RecyclerView.Adapter<RecyclerView.ViewHolder>
+{
+    public static final int ITEM_TYPE_EMPTY = Integer.MAX_VALUE - 1;
+
+    private RecyclerView.Adapter mInnerAdapter;
+    private View mEmptyView;
+    private int mEmptyLayoutId;
+
+
+    public EmptyWrapper(RecyclerView.Adapter adapter)
+    {
+        mInnerAdapter = adapter;
+    }
+
+    private boolean isEmpty()
+    {
+        return (mEmptyView != null || mEmptyLayoutId != 0) && mInnerAdapter.getItemCount() == 0;
+    }
+
+    @Override
+    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
+    {
+        if (isEmpty())
+        {
+            ViewHolder holder;
+            if (mEmptyView != null)
+            {
+                holder = ViewHolder.createViewHolder(parent.getContext(), mEmptyView);
+            } else
+            {
+                holder = ViewHolder.createViewHolder(parent.getContext(), parent, mEmptyLayoutId);
+            }
+            return holder;
+        }
+        return mInnerAdapter.onCreateViewHolder(parent, viewType);
+    }
+
+    @Override
+    public void onAttachedToRecyclerView(RecyclerView recyclerView)
+    {
+        WrapperUtils.onAttachedToRecyclerView(mInnerAdapter, recyclerView, new WrapperUtils.SpanSizeCallback()
+        {
+            @Override
+            public int getSpanSize(GridLayoutManager gridLayoutManager, GridLayoutManager.SpanSizeLookup oldLookup, int position)
+            {
+                if (isEmpty())
+                {
+                    return gridLayoutManager.getSpanCount();
+                }
+                if (oldLookup != null)
+                {
+                    return oldLookup.getSpanSize(position);
+                }
+                return 1;
+            }
+        });
+
+
+    }
+
+    @Override
+    public void onViewAttachedToWindow(RecyclerView.ViewHolder holder)
+    {
+        mInnerAdapter.onViewAttachedToWindow(holder);
+        if (isEmpty())
+        {
+            WrapperUtils.setFullSpan(holder);
+        }
+    }
+
+
+    @Override
+    public int getItemViewType(int position)
+    {
+        if (isEmpty())
+        {
+            return ITEM_TYPE_EMPTY;
+        }
+        return mInnerAdapter.getItemViewType(position);
+    }
+
+    @Override
+    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position)
+    {
+        if (isEmpty())
+        {
+            return;
+        }
+        mInnerAdapter.onBindViewHolder(holder, position);
+    }
+
+    @Override
+    public int getItemCount()
+    {
+        if (isEmpty()) {
+            return 1;
+        }
+        return mInnerAdapter.getItemCount();
+    }
+
+
+
+    public void setEmptyView(View emptyView)
+    {
+        mEmptyView = emptyView;
+    }
+
+    public void setEmptyView(int layoutId)
+    {
+        mEmptyLayoutId = layoutId;
+    }
+
+}

+ 152 - 0
adapter/src/main/java/com/itant/library/recyclerview/wrapper/HeaderAndFooterWrapper.java

@@ -0,0 +1,152 @@
+package com.itant.library.recyclerview.wrapper;
+
+
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.collection.SparseArrayCompat;
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.itant.library.recyclerview.base.ViewHolder;
+import com.itant.library.recyclerview.utils.WrapperUtils;
+
+
+public class HeaderAndFooterWrapper<T> extends RecyclerView.Adapter<RecyclerView.ViewHolder>
+{
+    private static final int BASE_ITEM_TYPE_HEADER = 100000;
+    private static final int BASE_ITEM_TYPE_FOOTER = 200000;
+
+    private SparseArrayCompat<View> mHeaderViews = new SparseArrayCompat<>();
+    private SparseArrayCompat<View> mFootViews = new SparseArrayCompat<>();
+
+    private RecyclerView.Adapter mInnerAdapter;
+
+    public HeaderAndFooterWrapper(RecyclerView.Adapter adapter)
+    {
+        mInnerAdapter = adapter;
+    }
+
+    @Override
+    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
+    {
+        if (mHeaderViews.get(viewType) != null)
+        {
+            ViewHolder holder = ViewHolder.createViewHolder(parent.getContext(), mHeaderViews.get(viewType));
+            return holder;
+
+        } else if (mFootViews.get(viewType) != null)
+        {
+            ViewHolder holder = ViewHolder.createViewHolder(parent.getContext(), mFootViews.get(viewType));
+            return holder;
+        }
+        return mInnerAdapter.onCreateViewHolder(parent, viewType);
+    }
+
+    @Override
+    public int getItemViewType(int position)
+    {
+        if (isHeaderViewPos(position))
+        {
+            return mHeaderViews.keyAt(position);
+        } else if (isFooterViewPos(position))
+        {
+            return mFootViews.keyAt(position - getHeadersCount() - getRealItemCount());
+        }
+        return mInnerAdapter.getItemViewType(position - getHeadersCount());
+    }
+
+    private int getRealItemCount()
+    {
+        return mInnerAdapter.getItemCount();
+    }
+
+
+    @Override
+    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position)
+    {
+        if (isHeaderViewPos(position))
+        {
+            return;
+        }
+        if (isFooterViewPos(position))
+        {
+            return;
+        }
+        mInnerAdapter.onBindViewHolder(holder, position - getHeadersCount());
+    }
+
+    @Override
+    public int getItemCount()
+    {
+        return getHeadersCount() + getFootersCount() + getRealItemCount();
+    }
+
+    @Override
+    public void onAttachedToRecyclerView(RecyclerView recyclerView)
+    {
+        WrapperUtils.onAttachedToRecyclerView(mInnerAdapter, recyclerView, new WrapperUtils.SpanSizeCallback()
+        {
+            @Override
+            public int getSpanSize(GridLayoutManager layoutManager, GridLayoutManager.SpanSizeLookup oldLookup, int position)
+            {
+                int viewType = getItemViewType(position);
+                if (mHeaderViews.get(viewType) != null)
+                {
+                    return layoutManager.getSpanCount();
+                } else if (mFootViews.get(viewType) != null)
+                {
+                    return layoutManager.getSpanCount();
+                }
+                if (oldLookup != null) {
+                    return oldLookup.getSpanSize(position);
+                }
+                return 1;
+            }
+        });
+    }
+
+    @Override
+    public void onViewAttachedToWindow(RecyclerView.ViewHolder holder)
+    {
+        mInnerAdapter.onViewAttachedToWindow(holder);
+        int position = holder.getLayoutPosition();
+        if (isHeaderViewPos(position) || isFooterViewPos(position))
+        {
+            WrapperUtils.setFullSpan(holder);
+        }
+    }
+
+    private boolean isHeaderViewPos(int position)
+    {
+        return position < getHeadersCount();
+    }
+
+    private boolean isFooterViewPos(int position)
+    {
+        return position >= getHeadersCount() + getRealItemCount();
+    }
+
+
+    public void addHeaderView(View view)
+    {
+        mHeaderViews.put(mHeaderViews.size() + BASE_ITEM_TYPE_HEADER, view);
+    }
+
+    public void addFootView(View view)
+    {
+        mFootViews.put(mFootViews.size() + BASE_ITEM_TYPE_FOOTER, view);
+    }
+
+    public int getHeadersCount()
+    {
+        return mHeaderViews.size();
+    }
+
+    public int getFootersCount()
+    {
+        return mFootViews.size();
+    }
+
+
+}

+ 161 - 0
adapter/src/main/java/com/itant/library/recyclerview/wrapper/LoadMoreWrapper.java

@@ -0,0 +1,161 @@
+package com.itant.library.recyclerview.wrapper;
+
+
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.StaggeredGridLayoutManager;
+
+import com.itant.library.recyclerview.base.ViewHolder;
+import com.itant.library.recyclerview.utils.WrapperUtils;
+
+
+public class LoadMoreWrapper<T> extends RecyclerView.Adapter<RecyclerView.ViewHolder>
+{
+    public static final int ITEM_TYPE_LOAD_MORE = Integer.MAX_VALUE - 2;
+
+    private RecyclerView.Adapter mInnerAdapter;
+    private View mLoadMoreView;
+    private int mLoadMoreLayoutId;
+
+    public LoadMoreWrapper(RecyclerView.Adapter adapter)
+    {
+        mInnerAdapter = adapter;
+    }
+
+    private boolean hasLoadMore()
+    {
+        return mLoadMoreView != null || mLoadMoreLayoutId != 0;
+    }
+
+
+    private boolean isShowLoadMore(int position)
+    {
+        return hasLoadMore() && (position >= mInnerAdapter.getItemCount());
+    }
+
+    @Override
+    public int getItemViewType(int position)
+    {
+        if (isShowLoadMore(position))
+        {
+            return ITEM_TYPE_LOAD_MORE;
+        }
+        return mInnerAdapter.getItemViewType(position);
+    }
+
+    @Override
+    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
+    {
+        if (viewType == ITEM_TYPE_LOAD_MORE)
+        {
+            ViewHolder holder;
+            if (mLoadMoreView != null)
+            {
+                holder = ViewHolder.createViewHolder(parent.getContext(), mLoadMoreView);
+            } else
+            {
+                holder = ViewHolder.createViewHolder(parent.getContext(), parent, mLoadMoreLayoutId);
+            }
+            return holder;
+        }
+        return mInnerAdapter.onCreateViewHolder(parent, viewType);
+    }
+
+    @Override
+    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position)
+    {
+        if (isShowLoadMore(position))
+        {
+            if (mOnLoadMoreListener != null)
+            {
+                mOnLoadMoreListener.onLoadMoreRequested();
+            }
+            return;
+        }
+        mInnerAdapter.onBindViewHolder(holder, position);
+    }
+
+    @Override
+    public void onAttachedToRecyclerView(RecyclerView recyclerView)
+    {
+        WrapperUtils.onAttachedToRecyclerView(mInnerAdapter, recyclerView, new WrapperUtils.SpanSizeCallback()
+        {
+            @Override
+            public int getSpanSize(GridLayoutManager layoutManager, GridLayoutManager.SpanSizeLookup oldLookup, int position)
+            {
+                if (isShowLoadMore(position))
+                {
+                    return layoutManager.getSpanCount();
+                }
+                if (oldLookup != null)
+                {
+                    return oldLookup.getSpanSize(position);
+                }
+                return 1;
+            }
+        });
+    }
+
+
+    @Override
+    public void onViewAttachedToWindow(RecyclerView.ViewHolder holder)
+    {
+        mInnerAdapter.onViewAttachedToWindow(holder);
+
+        if (isShowLoadMore(holder.getLayoutPosition()))
+        {
+            setFullSpan(holder);
+        }
+    }
+
+    private void setFullSpan(RecyclerView.ViewHolder holder)
+    {
+        ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
+
+        if (lp != null
+                && lp instanceof StaggeredGridLayoutManager.LayoutParams)
+        {
+            StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp;
+
+            p.setFullSpan(true);
+        }
+    }
+
+    @Override
+    public int getItemCount()
+    {
+        return mInnerAdapter.getItemCount() + (hasLoadMore() ? 1 : 0);
+    }
+
+
+    public interface OnLoadMoreListener
+    {
+        void onLoadMoreRequested();
+    }
+
+    private OnLoadMoreListener mOnLoadMoreListener;
+
+    public LoadMoreWrapper setOnLoadMoreListener(OnLoadMoreListener loadMoreListener)
+    {
+        if (loadMoreListener != null)
+        {
+            mOnLoadMoreListener = loadMoreListener;
+        }
+        return this;
+    }
+
+    public LoadMoreWrapper setLoadMoreView(View loadMoreView)
+    {
+        mLoadMoreView = loadMoreView;
+        return this;
+    }
+
+    public LoadMoreWrapper setLoadMoreView(int layoutId)
+    {
+        mLoadMoreLayoutId = layoutId;
+        return this;
+    }
+}

+ 13 - 0
adapter/src/main/res/anim/anim_bottom_in.xml

@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+     android:duration="500">
+
+    <translate
+        android:fromYDelta="50%"
+        android:toYDelta="0%"/>
+
+    <alpha
+        android:fromAlpha="0.5"
+        android:toAlpha="1"/>
+
+</set>

+ 4 - 0
adapter/src/main/res/values-v21/dimen.xml

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <dimen name="fab_margin">16dp</dimen>
+</resources>

+ 11 - 0
adapter/src/main/res/values/color.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <color name="color_primary_red">#f44336</color>
+    <color name="color_primary_red_dark">#d32f2f</color>
+    <color name="color_primary_green"> #4caf50</color>
+    <color name="color_primary_green_dark">#388e3c</color>
+    <color name="color_primary_blue">#2196f3</color>
+    <color name="color_primary_blue_dark">#1976d2</color>
+    <color name="color_accent_pink">#ff4081</color>
+    <color name="color_shadow">#44000000</color>
+</resources>

+ 5 - 0
adapter/src/main/res/values/dimen.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <dimen name="tabsHeight">48dp</dimen>
+    <dimen name="fab_margin">0dp</dimen>
+</resources>

+ 3 - 0
adapter/src/main/res/values/strings.xml

@@ -0,0 +1,3 @@
+<resources>
+    <string name="app_name">Library</string>
+</resources>

+ 22 - 0
adapter/src/main/res/values/styles.xml

@@ -0,0 +1,22 @@
+<resources>
+
+    <style name="CustomTheme" parent="Theme.AppCompat.Light.NoActionBar">
+    </style>
+
+    <style name="AppThemeRed" parent="CustomTheme">
+        <item name="colorPrimary">@color/color_primary_red</item>
+        <item name="colorPrimaryDark">@color/color_primary_red_dark</item>
+    </style>
+
+    <style name="AppThemeGreen" parent="CustomTheme">
+        <item name="colorPrimary">@color/color_primary_green</item>
+        <item name="colorPrimaryDark">@color/color_primary_green_dark</item>
+    </style>
+
+    <style name="AppThemeBlue" parent="CustomTheme">
+        <item name="colorPrimary">@color/color_primary_blue</item>
+        <item name="colorPrimaryDark">@color/color_primary_blue_dark</item>
+        <item name="colorAccent">@color/color_accent_pink</item>
+    </style>
+
+</resources>

+ 65 - 0
app/build.gradle

@@ -0,0 +1,65 @@
+apply plugin: 'com.android.application'
+//apply plugin: 'kotlin-android-extensions'
+//apply plugin: 'kotlin-android'
+
+android {
+    compileSdkVersion versions.compileSdk
+    buildToolsVersion versions.buildTools
+
+    defaultConfig {
+        minSdkVersion versions.minSdk
+        targetSdkVersion versions.targetSdk
+        applicationId "com.itant.shibei"
+        versionCode 1
+        versionName "1.0"
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+    }
+
+
+    compileOptions {
+        sourceCompatibility 1.8
+        targetCompatibility 1.8
+    }
+
+
+    signingConfigs {
+        config {
+            storeFile file('commonkey')
+            storePassword "away6899458"
+            keyAlias "sz"
+            keyPassword "away6899458"
+        }
+    }
+
+    buildTypes {
+        release {
+            signingConfig signingConfigs.config
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+    }
+}
+
+
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
+    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
+
+    testImplementation 'junit:junit:4.12'
+    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
+    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
+
+    api project(path: ':common')
+    implementation project(path: ':network')
+    implementation project(path: ':mvp')
+    implementation project(path: ':adapter')
+    //compile "androidx.core:core-ktx:+"
+    //compile "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
+    //implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+    implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
+
+}
+repositories {
+    mavenCentral()
+}

BIN
app/commonkey


+ 21 - 0
app/proguard-rules.pro

@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile

+ 27 - 0
app/src/androidTest/java/com/itant/shibei/ExampleInstrumentedTest.java

@@ -0,0 +1,27 @@
+package com.itant.shibei;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+    @Test
+    public void useAppContext() {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+
+        assertEquals("com.itant.shibei", appContext.getPackageName());
+    }
+}

+ 42 - 0
app/src/main/AndroidManifest.xml

@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    package="com.itant.shibei">
+
+    <uses-permission android:name="android.permission.INTERNET"/>
+
+    <application
+        android:icon="@mipmap/ic_launcher"
+        android:label="@string/app_name"
+        android:supportsRtl="true"
+        android:theme="@style/AppTheme"
+        tools:ignore="GoogleAppIndexingWarning"
+        android:allowBackup="false">
+        <activity
+            android:name=".ui.MainActivity"
+            android:label="@string/app_name"
+            android:screenOrientation="portrait">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".ui.mine.AboutActivity"
+            android:theme="@style/BackTheme"
+            android:screenOrientation="portrait"/>
+
+        <activity android:name=".ui.mine.login.LoginActivity"
+            android:theme="@style/TextInputStyle"
+            android:screenOrientation="portrait"/>
+
+        <activity android:name=".ui.mine.login.register.RegisterActivity"
+            android:theme="@style/TextInputStyle"
+            android:screenOrientation="portrait"/>
+        <activity android:name=".ui.mine.login.forget.ForgetActivity"
+            android:theme="@style/TextInputStyle"
+            android:screenOrientation="portrait"/>
+    </application>
+
+</manifest>

+ 32 - 0
app/src/main/java/com/itant/shibei/adapter/FragmentPagerItemAdapter.java

@@ -0,0 +1,32 @@
+package com.itant.shibei.adapter;
+
+
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentPagerAdapter;
+
+import java.util.List;
+
+/**
+ * Created by Jason on 2018/5/19.
+ */
+
+public class FragmentPagerItemAdapter extends FragmentPagerAdapter {
+
+    private List<Fragment> fragmentList;
+
+    public FragmentPagerItemAdapter(FragmentManager fm, List<Fragment> fragmentList) {
+        super(fm);
+        this.fragmentList = fragmentList;
+    }
+
+    @Override
+    public Fragment getItem(int position) {
+        return fragmentList.get(position);
+    }
+
+    @Override
+    public int getCount() {
+        return fragmentList.size();
+    }
+}

+ 114 - 0
app/src/main/java/com/itant/shibei/adapter/GoodsAdapter.java

@@ -0,0 +1,114 @@
+package com.itant.shibei.adapter;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Paint;
+import android.graphics.drawable.Drawable;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.widget.AppCompatImageView;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.load.engine.DiskCacheStrategy;
+import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
+import com.bumptech.glide.request.RequestOptions;
+import com.bumptech.glide.request.target.SimpleTarget;
+import com.bumptech.glide.request.transition.Transition;
+import com.itant.library.recyclerview.CommonAdapter;
+import com.itant.library.recyclerview.base.ViewHolder;
+import com.itant.shibei.R;
+import com.itant.shibei.bean.GoodsBean;
+import com.itant.shibei.common.ConstantString;
+import com.itant.shibei.tool.StringTool;
+import com.miekir.common.utils.ActivityTool;
+
+import java.util.List;
+
+/**
+ *
+ *
+ * @author 詹子聪
+ * @date 2020/7/6 20:08
+ * Description: 首页商品适配器
+ */
+public class GoodsAdapter extends CommonAdapter<GoodsBean> {
+    private Context mContext;
+    private int mRadius;
+
+    public GoodsAdapter(Context context, int layoutId, List<GoodsBean> goodsList) {
+        super(context, layoutId, goodsList);
+        mContext = context;
+        mRadius = (int) context.getResources().getDimension(R.dimen.margin_ss);
+    }
+
+
+    @Override
+    protected void convert(ViewHolder holder, GoodsBean goodsBean, int position) {
+        holder.setText(R.id.tv_title, goodsBean.getTitle());
+        holder.setText(R.id.tv_shop_name, goodsBean.getShopName());
+
+        // 好评
+        holder.setText(R.id.tv_good_comment,
+                String.format(ConstantString.GOOD_COMMENT, Math.round(goodsBean.getGoodCommentPercent()*100)));
+
+        // 月销
+        holder.setText(R.id.tv_sales_per_month,
+                String.format(ConstantString.SALES_PER_MONTH, String.valueOf(goodsBean.getSalesPerMonth())));
+
+        // 返现
+        TextView tv_rebate = holder.getView(R.id.tv_rebate);
+        tv_rebate.setText(String.format(ConstantString.MONEY_GAME,
+                StringTool.getShowMoney(goodsBean.getOldPrice()-goodsBean.getNowPrice())));
+        // 走马灯
+        tv_rebate.setSelected(true);
+
+        // 自营
+        TextView tv_self = holder.getView(R.id.tv_self);
+        if (goodsBean.isSelfBusiness()) {
+            tv_self.setVisibility(View.VISIBLE);
+        } else {
+            tv_self.setVisibility(View.GONE);
+        }
+
+        // 原价
+        TextView tv_old_price = holder.getView(R.id.tv_old_price);
+        tv_old_price.setText(String.format(ConstantString.MONEY_RMB, StringTool.getShowMoney(goodsBean.getOldPrice())));
+        // 增加删除线
+        tv_old_price.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG);
+
+        // 现价
+        holder.setText(R.id.tv_now_price, String.format(ConstantString.MONEY_RMB, StringTool.getShowMoney(goodsBean.getNowPrice())));
+
+        // 一句话推荐
+        TextView tv_reason = holder.getView(R.id.tv_reason);
+        tv_reason.setText(goodsBean.getReason());
+
+        holder.setOnClickListener(R.id.cv_goods, new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                String goodsUrl = goodsBean.getGoodsUrl();
+                ActivityTool.openUrl((Activity) mContext, goodsUrl);
+            }
+        });
+
+        AppCompatImageView aciv_goods = holder.getView(R.id.aciv_goods);
+        Glide.with(mContext).load(goodsBean.getCoverImageUrl())
+                .apply(RequestOptions.bitmapTransform(new RoundedCorners(mRadius)))
+                .apply(new RequestOptions()
+                        .skipMemoryCache(true)
+                        .diskCacheStrategy(DiskCacheStrategy.NONE))
+                //先加载原图大小的十分之一
+                .thumbnail(0.1f)
+                .into(new SimpleTarget<Drawable>() {
+                    @Override
+                    public void onResourceReady(Drawable resource, Transition<? super Drawable> transition) {
+                        aciv_goods.setScaleType(ImageView.ScaleType.CENTER_CROP);
+                        aciv_goods.setImageDrawable(resource);
+                    }
+                });
+    }
+}

+ 70 - 0
app/src/main/java/com/itant/shibei/adapter/TemplateAdapter.java

@@ -0,0 +1,70 @@
+package com.itant.shibei.adapter;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.view.View;
+import android.widget.ImageView;
+
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.load.engine.DiskCacheStrategy;
+import com.bumptech.glide.request.RequestOptions;
+import com.bumptech.glide.request.target.SimpleTarget;
+import com.bumptech.glide.request.transition.Transition;
+import com.itant.library.recyclerview.CommonAdapter;
+import com.itant.library.recyclerview.base.ViewHolder;
+import com.itant.shibei.R;
+import com.itant.shibei.bean.TemplateBean;
+import com.miekir.common.utils.ActivityTool;
+import com.miekir.common.utils.ToastTool;
+
+import java.util.List;
+
+/**
+ *
+ *
+ * @author 詹子聪
+ * @date 2020/7/6 20:08
+ * Description: 首页商品适配器
+ */
+public class TemplateAdapter extends CommonAdapter<TemplateBean> {
+    private List<TemplateBean> mTemplateList;
+
+    public TemplateAdapter(Context context, int layoutId, List<TemplateBean> templateBeanList) {
+        super(context, layoutId, templateBeanList);
+        mTemplateList = templateBeanList;
+    }
+
+
+    @Override
+    protected void convert(ViewHolder holder, TemplateBean templateBean, int position) {
+        ImageView iv_template = holder.getView(R.id.iv_template);
+        // 圆角
+        Glide.with(mContext).load(templateBean.getCoverUrl())
+                //.apply(RequestOptions.bitmapTransform(new RoundedCorners(48))
+                .apply(new RequestOptions()
+                        .skipMemoryCache(true)
+                        .diskCacheStrategy(DiskCacheStrategy.NONE))
+                //先加载原图大小的十分之一
+                .thumbnail(0.1f)
+                .into(new SimpleTarget<Drawable>() {
+                    @Override
+                    public void onResourceReady(Drawable resource, Transition<? super Drawable> transition) {
+                        iv_template.setScaleType(ImageView.ScaleType.CENTER_CROP);
+                        iv_template.setImageDrawable(resource);
+                    }
+                });
+
+        holder.setText(R.id.tv_template, templateBean.getTemplateName());
+        holder.setOnClickListener(R.id.rl_template, new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (templateBean.isActionEnable()) {
+                    ActivityTool.openUrl((Activity) mContext, templateBean.getJumpUrl());
+                } else {
+                    ToastTool.showShort("敬请期待");
+                }
+            }
+        });
+    }
+}

+ 60 - 0
app/src/main/java/com/itant/shibei/base/BaseShiBeiActivity.java

@@ -0,0 +1,60 @@
+package com.itant.shibei.base;
+
+import android.os.Build;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ImageView;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+
+import com.itant.shibei.R;
+import com.miekir.mvp.view.BaseMVPActivity;
+
+/**
+ *
+ *
+ * @author 詹子聪
+ * @date 2020/6/18 16:47
+ * Description: 界面基类
+ */
+public abstract class BaseShiBeiActivity extends BaseMVPActivity {
+    private View iv_done;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        // 状态栏深色模式,改变状态栏文字颜色
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            getWindow().getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN|View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
+        }
+    }
+
+    protected void setOnDoneListener(View.OnClickListener onDoneListener) {
+        if (iv_done == null) {
+            return;
+        }
+        iv_done.setVisibility(View.VISIBLE);
+        iv_done.setOnClickListener(onDoneListener);
+    }
+    protected void setTitle(String title) {
+        //iv_done = findViewById(R.id.iv_done);
+        Toolbar toolbar = findViewById(R.id.toolbar);
+        if (toolbar == null) {
+            return;
+        }
+        toolbar.setTitle(title);
+        //toolbar.setTitleTextColor(getResources().getColor(R.color.black_theme));
+
+        setSupportActionBar(toolbar);
+        //关键下面两句话,设置了回退按钮,及点击事件的效果
+        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                finish();
+            }
+        });
+    }
+}

+ 138 - 0
app/src/main/java/com/itant/shibei/bean/BeiUser.java

@@ -0,0 +1,138 @@
+package com.itant.shibei.bean;
+
+/**
+ * Created by Jason on 2018/8/26.
+ */
+
+public class BeiUser {
+    private String email;
+    private String nickName;
+    private String autograph;
+    private String password;
+    private String headIcon;
+    private int sex;
+    private String token;
+    private long registerTimeMillis;
+    private long lastLoginTimeMillis;
+    private boolean isVip;
+    private String deviceId;
+    private String lastIp;
+    private int themeMode;
+
+    /**
+     * 余额
+     */
+    private double money;
+
+    public String getAutograph() {
+        return autograph;
+    }
+
+    public void setAutograph(String autograph) {
+        this.autograph = autograph;
+    }
+
+    public String getEmail() {
+        return email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    public String getNickName() {
+        return nickName;
+    }
+
+    public void setNickName(String nickName) {
+        this.nickName = nickName;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public String getHeadIcon() {
+        return headIcon;
+    }
+
+    public void setHeadIcon(String headIcon) {
+        this.headIcon = headIcon;
+    }
+
+    public int getSex() {
+        return sex;
+    }
+
+    public void setSex(int sex) {
+        this.sex = sex;
+    }
+
+    public String getToken() {
+        return token;
+    }
+
+    public void setToken(String token) {
+        this.token = token;
+    }
+
+    public long getRegisterTimeMillis() {
+        return registerTimeMillis;
+    }
+
+    public void setRegisterTimeMillis(long registerTimeMillis) {
+        this.registerTimeMillis = registerTimeMillis;
+    }
+
+    public long getLastLoginTimeMillis() {
+        return lastLoginTimeMillis;
+    }
+
+    public void setLastLoginTimeMillis(long lastLoginTimeMillis) {
+        this.lastLoginTimeMillis = lastLoginTimeMillis;
+    }
+
+    public boolean isVip() {
+        return isVip;
+    }
+
+    public void setVip(boolean vip) {
+        isVip = vip;
+    }
+
+    public String getDeviceId() {
+        return deviceId;
+    }
+
+    public void setDeviceId(String deviceId) {
+        this.deviceId = deviceId;
+    }
+
+    public String getLastIp() {
+        return lastIp;
+    }
+
+    public void setLastIp(String lastIp) {
+        this.lastIp = lastIp;
+    }
+
+    public int getThemeMode() {
+        return themeMode;
+    }
+
+    public void setThemeMode(int themeMode) {
+        this.themeMode = themeMode;
+    }
+
+    public double getMoney() {
+        return money;
+    }
+
+    public void setMoney(double money) {
+        this.money = money;
+    }
+}

+ 234 - 0
app/src/main/java/com/itant/shibei/bean/GoodsBean.java

@@ -0,0 +1,234 @@
+package com.itant.shibei.bean;
+
+/**
+ *
+ *
+ * @author 詹子聪
+ * @date 2020/7/5 21:50
+ * Description: 商品实体
+ */
+public class GoodsBean {
+    public static final int TYPE_TECHNOLOGY = 1;
+    public static final int TYPE_LIFE = 2;
+    public static final int TYPE_NETWORK = 3;
+
+
+    /**
+     * 商品id
+     */
+    private String goodsId;
+    /**
+     * 封面图片地址
+     */
+    private String coverImageUrl;
+    /**
+     * 标题
+     */
+    private String title;
+    /**
+     * 商品描述
+     */
+    private String description;
+    /**
+     * 商品推荐理由(一句话推荐、推荐者心声)
+     */
+    private String reason;
+    /**
+     * 原价
+     */
+    private double oldPrice;
+    /**
+     * 现价
+     */
+    private double nowPrice;
+    /**
+     * 返利
+     */
+    private String rebate;
+    /**
+     * 店名
+     */
+    private String shopName;
+    /**
+     * 商店所属省份
+     */
+    private String province;
+    /**
+     * 是否自营
+     */
+    private boolean isSelfBusiness;
+    /**
+     * 是否有券
+     */
+    private boolean hasCoupon;
+    /**
+     * 优惠券金额
+     */
+    private String couponMoney;
+    /**
+     * 所属类型
+     */
+    private int goodsType;
+    /**
+     * 商品链接
+     */
+    private String goodsUrl;
+    /**
+     * 月销量
+     */
+    private int salesPerMonth;
+
+    /**
+     * 评论条数
+     */
+    private int commentNum;
+
+    /**
+     * 好评率
+     */
+    private double goodCommentPercent;
+
+    public String getGoodsId() {
+        return goodsId;
+    }
+
+    public void setGoodsId(String goodsId) {
+        this.goodsId = goodsId;
+    }
+
+    public String getCoverImageUrl() {
+        return coverImageUrl;
+    }
+
+    public void setCoverImageUrl(String coverImageUrl) {
+        this.coverImageUrl = coverImageUrl;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public double getOldPrice() {
+        return oldPrice;
+    }
+
+    public void setOldPrice(double oldPrice) {
+        this.oldPrice = oldPrice;
+    }
+
+    public double getNowPrice() {
+        return nowPrice;
+    }
+
+    public void setNowPrice(double nowPrice) {
+        this.nowPrice = nowPrice;
+    }
+
+    public String getRebate() {
+        return rebate;
+    }
+
+    public void setRebate(String rebate) {
+        this.rebate = rebate;
+    }
+
+    public String getShopName() {
+        return shopName;
+    }
+
+    public void setShopName(String shopName) {
+        this.shopName = shopName;
+    }
+
+    public String getProvince() {
+        return province;
+    }
+
+    public void setProvince(String province) {
+        this.province = province;
+    }
+
+    public boolean isSelfBusiness() {
+        return isSelfBusiness;
+    }
+
+    public void setSelfBusiness(boolean selfBusiness) {
+        isSelfBusiness = selfBusiness;
+    }
+
+    public boolean isHasCoupon() {
+        return hasCoupon;
+    }
+
+    public void setHasCoupon(boolean hasCoupon) {
+        this.hasCoupon = hasCoupon;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public String getReason() {
+        return reason;
+    }
+
+    public void setReason(String reason) {
+        this.reason = reason;
+    }
+
+    public int getGoodsType() {
+        return goodsType;
+    }
+
+    public void setGoodsType(int goodsType) {
+        this.goodsType = goodsType;
+    }
+
+    public String getCouponMoney() {
+        return couponMoney;
+    }
+
+    public void setCouponMoney(String couponMoney) {
+        this.couponMoney = couponMoney;
+    }
+
+    public String getGoodsUrl() {
+        return goodsUrl;
+    }
+
+    public void setGoodsUrl(String goodsUrl) {
+        this.goodsUrl = goodsUrl;
+    }
+
+    public int getSalesPerMonth() {
+        return salesPerMonth;
+    }
+
+    public void setSalesPerMonth(int salesPerMonth) {
+        this.salesPerMonth = salesPerMonth;
+    }
+
+    public int getCommentNum() {
+        return commentNum;
+    }
+
+    public void setCommentNum(int commentNum) {
+        this.commentNum = commentNum;
+    }
+
+    public double getGoodCommentPercent() {
+        return goodCommentPercent;
+    }
+
+    public void setGoodCommentPercent(double goodCommentPercent) {
+        this.goodCommentPercent = goodCommentPercent;
+    }
+}

+ 88 - 0
app/src/main/java/com/itant/shibei/bean/TemplateBean.java

@@ -0,0 +1,88 @@
+package com.itant.shibei.bean;
+
+import com.itant.shibei.common.ConstantUrl;
+
+/**
+ *
+ *
+ * @author 詹子聪
+ * @date 2020/7/7 19:37
+ * Description: 模板实体
+ */
+public class TemplateBean {
+    /**
+     * 模板Id
+     */
+    private int templateId;
+    /**
+     * 模板类型
+     */
+    private int templateType;
+
+    /**
+     * 模板名称
+     */
+    private String templateName;
+    /**
+     * 点击之后跳转的链接
+     */
+    private String jumpUrl;
+    /**
+     * 封面图片URL
+     */
+    private String coverUrl = ConstantUrl.URL_RANDOM_PHOTO_WALLPAPER;
+
+
+    /**
+     * 是否可以响应点击
+     */
+    private boolean actionEnable;
+
+    public int getTemplateId() {
+        return templateId;
+    }
+
+    public void setTemplateId(int templateId) {
+        this.templateId = templateId;
+    }
+
+    public String getTemplateName() {
+        return templateName;
+    }
+
+    public void setTemplateName(String templateName) {
+        this.templateName = templateName;
+    }
+
+    public String getJumpUrl() {
+        return jumpUrl;
+    }
+
+    public void setJumpUrl(String jumpUrl) {
+        this.jumpUrl = jumpUrl;
+    }
+
+    public String getCoverUrl() {
+        return coverUrl;
+    }
+
+    public void setCoverUrl(String coverUrl) {
+        this.coverUrl = coverUrl;
+    }
+
+    public boolean isActionEnable() {
+        return actionEnable;
+    }
+
+    public void setActionEnable(boolean actionEnable) {
+        this.actionEnable = actionEnable;
+    }
+
+    public int getTemplateType() {
+        return templateType;
+    }
+
+    public void setTemplateType(int templateType) {
+        this.templateType = templateType;
+    }
+}

+ 15 - 0
app/src/main/java/com/itant/shibei/common/ConstantString.java

@@ -0,0 +1,15 @@
+package com.itant.shibei.common;
+
+/**
+ * Copyright (C), 2019-2020, Genlot
+ *
+ * @author 詹子聪
+ * @date 2020/7/11 16:35
+ * Description: 常量字符串
+ */
+public interface ConstantString {
+    String MONEY_RMB = "¥%s";
+    String SALES_PER_MONTH = "月销 %s";
+    String GOOD_COMMENT = "%s%%";
+    String MONEY_GAME = "%sG";
+}

+ 32 - 0
app/src/main/java/com/itant/shibei/common/ConstantUrl.java

@@ -0,0 +1,32 @@
+package com.itant.shibei.common;
+
+/**
+ *
+ *
+ * @author 詹子聪
+ * @date 2020/7/5 11:27
+ * Description: 常量
+ */
+public interface ConstantUrl {
+
+    /**
+     * 壁纸
+     */
+    String URL_RANDOM_PHOTO_WALLPAPER = "https://uploadbeta.com/api/pictures/random/?key=BingEverydayWallpaperPicture";
+
+    /**
+     * 京东装机模板
+     */
+    String URL_JD_TEMPLATE_COMPUTER = "https://diy.m.jd.com/?utm_user=plusmember&ad_od=share&utm_source=androidapp&utm_medium=appshare&utm_campaign=t_335139774&utm_term=CopyURL";
+
+    /**
+     * 美团优惠
+     */
+    String URL_MEITUAN_BONUS = "http://p.yiqifa.com/l?l=Cl7SYKqBR9et6lMdUJqSpNM2W9sWgQ446wbQNcUJWKe6pBU1C9qQYcDm696WNsUdUtqQN9U25KV6KlB7Y7yS5cy2W9sWgEM1UmBQgPUVNPAWgpMEUQ4SM5e7KOosR96y!5F9UnsuUZgLRlu_fOwdY5PAUZPbY8eEYO7_3QULfOb9Mpo8YJoECSo8MJMw6O4w6NUy6O3_6lKSWNK_C5ewMQzdCZgVYj--";
+
+    /**
+     * 二次元
+     */
+    String URL_RANDOM_PHOTO_ECY = "https://uploadbeta.com/api/pictures/random/?key=二次元";
+    //String URL_RANDOM_PHOTO_ECY = "https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1594032996&di=6b8d48217739c2555a4b05b931cc45d7&src=http://a3.att.hudong.com/14/75/01300000164186121366756803686.jpg";
+}

+ 80 - 0
app/src/main/java/com/itant/shibei/tool/DataTool.java

@@ -0,0 +1,80 @@
+package com.itant.shibei.tool;
+
+import com.itant.shibei.bean.GoodsBean;
+import com.itant.shibei.bean.TemplateBean;
+import com.itant.shibei.common.ConstantUrl;
+import com.itant.shibei.ui.function.FunctionFragment;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ *
+ * @author 詹子聪
+ * @date 2020/7/8 19:36
+ * Description: 模拟数据提供者
+ */
+public class DataTool {
+    private DataTool() {
+    }
+
+    public static List<TemplateBean> getTemplateList(int functionTye) {
+        TemplateBean templateBean = new TemplateBean();
+
+        switch (functionTye) {
+            case FunctionFragment.TEMPLATE_TYPE_BONUS:
+                templateBean.setCoverUrl(ConstantUrl.URL_RANDOM_PHOTO_WALLPAPER);
+                templateBean.setTemplateName("美团优惠券");
+                templateBean.setJumpUrl(ConstantUrl.URL_MEITUAN_BONUS);
+                templateBean.setActionEnable(true);
+                break;
+            case FunctionFragment.TEMPLATE_TYPE_TEMPLATE:
+                templateBean.setCoverUrl(ConstantUrl.URL_RANDOM_PHOTO_ECY);
+                templateBean.setTemplateName("DIY装机");
+                templateBean.setJumpUrl(ConstantUrl.URL_JD_TEMPLATE_COMPUTER);
+                templateBean.setActionEnable(true);
+                break;
+
+            case FunctionFragment.TEMPLATE_TYPE_GAME:
+                templateBean.setCoverUrl(ConstantUrl.URL_RANDOM_PHOTO_ECY);
+                templateBean.setTemplateName("欢乐猜猜");
+                templateBean.setActionEnable(false);
+                break;
+            default:
+                break;
+        }
+
+        List<TemplateBean> templateBeanList = new ArrayList<>();
+        templateBeanList.add(templateBean);
+        return templateBeanList;
+    }
+
+    public static List<GoodsBean> getGoodsList() {
+        List<GoodsBean> goodsList = new ArrayList<>();
+        GoodsBean goodsBean = new GoodsBean();
+        goodsBean.setCoverImageUrl("https://img14.360buyimg.com/n0/jfs/t1/97822/29/10664/255856/5e1ebf26Eea1a28ec/ac2c298127bae9a4.jpg");
+        goodsBean.setTitle("华硕(ASUS) PN60 商用办公家用教育 台式机电脑主机 (i7-8550U 256G SSD 8G 正版Win10 三年上门)迷你台式");
+        goodsBean.setDescription("远程教育,在家办公,顺畅不卡顿!酷睿i7-8550U处理器、256GSSD,8G内存,便携电脑移动办公更强性能购买PN61-i7,高效稳定");
+        goodsBean.setReason("小巧便携且高效稳定");
+        goodsBean.setOldPrice(3899);
+        goodsBean.setNowPrice(3849);
+        goodsBean.setRebate("50");
+        goodsBean.setShopName("华硕京东自营旗舰店");
+        goodsBean.setProvince("广东");
+        goodsBean.setSelfBusiness(true);
+        goodsBean.setHasCoupon(true);
+        goodsBean.setCouponMoney("30");
+        goodsBean.setGoodsType(GoodsBean.TYPE_TECHNOLOGY);
+        goodsBean.setGoodsUrl("https://union-click.jd.com/jdc?e=&p=AyIGZRtcEgAXA1QfWhIyEgZUGlocChIFVBJeJUZNXwtEa0xHV0YXEEULWldTCQQHCllHGAdFBwtEQkQBBRxNVlQYBUkeTVxNCRNLGEF6RwtVGloUAxsPVRlaHAciVR1hWBNYZl42cCVPUVF6V1skdFxJZ1kXaxQyEgZUGFMcBREAUitrFQUiVDtADnsGQQBWH1JHCxMCUksOJQMiB1ETXhYKGwFdHVsQByIAVRJrU1dTWhNNBEtnbFMSRQYlMiIEZStrFTIRNxd1WBYLFVcAEg8dUkcFUE9THAsbBl0aWRBSFwIFTl8VChI3VxpaEQs%3D");
+        goodsBean.setSalesPerMonth(1022);
+        goodsBean.setGoodCommentPercent(0.98d);
+        goodsList.add(goodsBean);
+        goodsList.add(goodsBean);
+        goodsList.add(goodsBean);
+        goodsList.add(goodsBean);
+        goodsList.add(goodsBean);
+        goodsList.add(goodsBean);
+        return goodsList;
+    }
+}

+ 19 - 0
app/src/main/java/com/itant/shibei/tool/StringTool.java

@@ -0,0 +1,19 @@
+package com.itant.shibei.tool;
+
+import java.text.DecimalFormat;
+
+/**
+ * Copyright (C), 2019-2020, Genlot
+ *
+ * @author 詹子聪
+ * @date 2020/7/11 21:59
+ * Description: 字符串相关工具
+ */
+public class StringTool {
+    private StringTool() {}
+
+    private static final DecimalFormat FORMAT_TWO = new DecimalFormat("#.00");
+    public static String getShowMoney(double number) {
+        return FORMAT_TWO.format(number);
+    }
+}

+ 83 - 0
app/src/main/java/com/itant/shibei/tool/SystemTool.java

@@ -0,0 +1,83 @@
+package com.itant.shibei.tool;
+
+import android.app.Activity;
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+
+import com.miekir.common.utils.ToastTool;
+
+
+/**
+ * Created by Jason on 2018/9/11.
+ */
+
+public class SystemTool {
+    private SystemTool() {}
+    private static final String LABEL_COPY = "shi_bei";
+    public static boolean copyText(Context context, String text) {
+        ClipboardManager manager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
+        ClipData clipData = ClipData.newPlainText(LABEL_COPY, text);
+        if (manager != null) {
+            manager.setPrimaryClip(clipData);
+            return true;
+        }
+        return false;
+    }
+
+    public static int getVersionCode(Context context) {
+        int versionCode = -1;
+        PackageManager packageManager = context.getPackageManager();
+        try {
+            if (packageManager != null) {
+                PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
+                return packageInfo.versionCode;
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return versionCode;
+    }
+
+    public static String getVersionName(Context context) {
+        PackageManager manager = context.getPackageManager();
+        if (manager != null) {
+            try {
+                //获取软件版本号,对应AndroidManifest.xml下android:versionCode,0表示基本信息
+                return manager.getPackageInfo(context.getPackageName(), 0).versionName;
+            } catch (PackageManager.NameNotFoundException e) {
+                e.printStackTrace();
+            }
+        }
+        return "";
+    }
+
+    /**
+     * 发送邮件
+     * @param activity
+     */
+    public static void sendEmail(Activity activity) {
+        if (activity == null) {
+            return;
+        }
+
+        boolean copyResult = SystemTool.copyText(activity, "[email protected]");
+        if (!copyResult) {
+            ToastTool.showLong("请发送到[email protected]");
+        } else {
+            ToastTool.showShort("已复制反馈邮箱号");
+        }
+        Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
+        emailIntent.setType("application/octet-stream");
+        try {
+            activity.startActivity(emailIntent);
+        } catch (Exception e) {
+            e.printStackTrace();
+            ToastTool.showShort("未找到邮箱客户端");
+        }
+    }
+}

+ 90 - 0
app/src/main/java/com/itant/shibei/ui/MainActivity.java

@@ -0,0 +1,90 @@
+package com.itant.shibei.ui;
+
+import android.os.Bundle;
+import android.view.MenuItem;
+import android.view.View;
+
+import com.google.android.material.bottomnavigation.BottomNavigationView;
+import com.google.android.material.bottomnavigation.LabelVisibilityMode;
+import com.itant.shibei.R;
+import com.itant.shibei.adapter.FragmentPagerItemAdapter;
+import com.itant.shibei.base.BaseShiBeiActivity;
+import com.itant.shibei.ui.function.FunctionFragment;
+import com.itant.shibei.ui.home.HomeFragment;
+import com.itant.shibei.ui.mine.MineFragment;
+
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
+import androidx.navigation.NavController;
+import androidx.viewpager.widget.ViewPager;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class MainActivity extends BaseShiBeiActivity implements View.OnClickListener {
+
+    private NavController navController;
+    private ViewPager vp_main;
+    private List<Fragment> fragmentList;
+
+
+
+    @Override
+    public int getLayoutID() {
+        return R.layout.activity_main;
+    }
+
+    @Override
+    public void initViews(Bundle savedInstanceState) {
+        BottomNavigationView nav_view = findViewById(R.id.nav_view);
+        // 去除底部动画效果
+        //BottomNavigationViewHelper.disableShiftMode(navigation);
+        nav_view.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
+        // 底部导航菜单3个项以上不显示文字的问题
+        nav_view.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);
+        // 避免在当前Fragment点击当前Fragment对应的Tab时仍然被销毁
+        nav_view.setOnNavigationItemReselectedListener(item -> {
+            // do nothing here
+        });
+
+        // 采用ViewPager+BottomNavigationView防止每次切换Tab时Fragment都被销毁
+        fragmentList = new ArrayList<>();
+        fragmentList.add(new HomeFragment());
+        fragmentList.add(new FunctionFragment());
+        fragmentList.add(new MineFragment());
+        vp_main = findViewById(R.id.vp_main);
+        vp_main.setOffscreenPageLimit(fragmentList.size());
+
+        FragmentPagerItemAdapter adapter = new FragmentPagerItemAdapter(getSupportFragmentManager(), fragmentList);
+        vp_main.setAdapter(adapter);
+        vp_main.setCurrentItem(0);
+    }
+
+    private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
+            = new BottomNavigationView.OnNavigationItemSelectedListener() {
+
+        @Override
+        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
+            switch (item.getItemId()) {
+                case R.id.nav_home:
+                    vp_main.setCurrentItem(0);
+                    return true;
+                case R.id.nav_template:
+                    vp_main.setCurrentItem(1);
+                    return true;
+                case R.id.nav_mine:
+                    vp_main.setCurrentItem(2);
+                    return true;
+                default:
+                    break;
+            }
+            return false;
+        }
+    };
+
+
+    @Override
+    public void onClick(View v) {
+
+    }
+}

+ 46 - 0
app/src/main/java/com/itant/shibei/ui/MainViewModel.java

@@ -0,0 +1,46 @@
+package com.itant.shibei.ui;
+
+import android.view.View;
+
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.MutableLiveData;
+import androidx.lifecycle.ViewModel;
+
+/**
+ * 使用ViewModel保存Fragment的数据,阻止Fragment在配合BottomNavigationView切换时总被销毁的问题
+ */
+public class MainViewModel extends ViewModel {
+    private MutableLiveData<View> mTemplateView;
+    private MutableLiveData<View> mHomeView;
+    private MutableLiveData<View> mMineView;
+
+    public MainViewModel() {
+        mTemplateView = new MutableLiveData<>();
+        mHomeView = new MutableLiveData<>();
+        mMineView = new MutableLiveData<>();
+    }
+
+    public void setTemplateView(View v) {
+        mTemplateView.setValue(v);
+    }
+
+    public void setHomeView(View v) {
+        mHomeView.setValue(v);
+    }
+
+    public void setMineView(View v) {
+        mMineView.setValue(v);
+    }
+
+    public LiveData<View> getTemplateView() {
+        return mTemplateView;
+    }
+
+    public LiveData<View> getHomeView() {
+        return mHomeView;
+    }
+
+    public LiveData<View> getMineView() {
+        return mMineView;
+    }
+}

+ 48 - 0
app/src/main/java/com/itant/shibei/ui/function/FunctionFragment.java

@@ -0,0 +1,48 @@
+package com.itant.shibei.ui.function;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
+import androidx.viewpager.widget.ViewPager;
+
+import com.flyco.tablayout.SlidingTabLayout;
+import com.itant.shibei.R;
+import com.itant.shibei.ui.function.template.TemplateFragment;
+import com.miekir.common.adapter.TabFragmentAdapter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 模板Fragment
+ */
+public class FunctionFragment extends Fragment {
+    public static final int TEMPLATE_TYPE_BONUS = 1;
+    public static final int TEMPLATE_TYPE_TEMPLATE = 2;
+    public static final int TEMPLATE_TYPE_GAME = 3;
+
+    @Override
+    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+
+        View root = inflater.inflate(R.layout.fragment_function, container, false);
+        String[] titles = {"游戏", "优惠", "模板"};
+        List<Fragment> fragments = new ArrayList<>();
+        fragments.add(new TemplateFragment(TEMPLATE_TYPE_GAME));
+        fragments.add(new TemplateFragment(TEMPLATE_TYPE_BONUS));
+        fragments.add(new TemplateFragment(TEMPLATE_TYPE_TEMPLATE));
+
+        ViewPager vp_home = root.findViewById(R.id.vp_home);
+        TabFragmentAdapter adapter = new TabFragmentAdapter(getChildFragmentManager(), fragments);
+        vp_home.setAdapter(adapter);
+        vp_home.setOffscreenPageLimit(titles.length);
+        //vp_home.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
+
+        SlidingTabLayout stl_home = root.findViewById(R.id.stl_home);
+        stl_home.setViewPager(vp_home, titles);
+        return root;
+    }
+}

+ 17 - 0
app/src/main/java/com/itant/shibei/ui/function/template/ITemplateView.java

@@ -0,0 +1,17 @@
+package com.itant.shibei.ui.function.template;
+
+import com.itant.shibei.bean.TemplateBean;
+import com.miekir.mvp.view.IView;
+
+import java.util.List;
+
+/**
+ *
+ *
+ * @author 詹子聪
+ * @date 2020/7/8 19:44
+ * Description: Template的View
+ */
+public interface ITemplateView extends IView {
+    void onTemplateDataCome(List<TemplateBean> templateBeanList);
+}

+ 61 - 0
app/src/main/java/com/itant/shibei/ui/function/template/TemplateFragment.java

@@ -0,0 +1,61 @@
+package com.itant.shibei.ui.function.template;
+
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.itant.library.recyclerview.CommonAdapter;
+import com.itant.shibei.R;
+import com.itant.shibei.adapter.TemplateAdapter;
+import com.itant.shibei.bean.TemplateBean;
+import com.itant.shibei.ui.function.FunctionFragment;
+import com.miekir.mvp.presenter.InjectPresenter;
+import com.miekir.mvp.view.BaseMVPFragment;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 模板Fragment
+ */
+public class TemplateFragment extends BaseMVPFragment implements ITemplateView {
+    private int mTemplateType = FunctionFragment.TEMPLATE_TYPE_BONUS;
+    private List<TemplateBean> mTemplateBeanList = new ArrayList<>();
+    private CommonAdapter<TemplateBean> mAdapter;
+
+    @InjectPresenter
+    TemplatePresenter mPresenter;
+
+    public TemplateFragment(int templateType) {
+        mTemplateType = templateType;
+    }
+
+    @Override
+    public int getLayoutResId() {
+        return R.layout.fragment_function_template;
+    }
+
+    @Override
+    public void onCreateViewFinished(@Nullable Bundle savedInstanceState) {
+        super.onCreateViewFinished(savedInstanceState);
+
+        RecyclerView rv_template = rootView.findViewById(R.id.rv_template);
+        // 必须要设置LayoutManager,否则RecyclerView不知道要使用什么布局,从而在界面上不显示
+        LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false);
+        rv_template.setLayoutManager(layoutManager);
+        mAdapter = new TemplateAdapter(getActivity(), R.layout.item_template, mTemplateBeanList);
+        rv_template.setAdapter(mAdapter);
+
+        // 从服务器获取数据
+        mPresenter.getTemplateData(mTemplateType);
+    }
+
+    @Override
+    public void onTemplateDataCome(List<TemplateBean> templateBeanList) {
+        // todo 分页,判断是否第0页(下拉刷新)
+        mTemplateBeanList.addAll(templateBeanList);
+        mAdapter.notifyDataSetChanged();
+    }
+}

+ 28 - 0
app/src/main/java/com/itant/shibei/ui/function/template/TemplatePresenter.java

@@ -0,0 +1,28 @@
+package com.itant.shibei.ui.function.template;
+
+import com.itant.shibei.bean.TemplateBean;
+import com.itant.shibei.tool.DataTool;
+import com.miekir.mvp.presenter.BasePresenter;
+
+import java.util.List;
+
+/**
+ *
+ *
+ * @author 詹子聪
+ * @date 2020/7/8 19:43
+ * Description: 模板的Presenter
+ */
+public class TemplatePresenter extends BasePresenter<ITemplateView> {
+
+    /**
+     * todo 从服务器获取数据,切换线程
+     * @param functionType
+     */
+    public void getTemplateData(int functionType) {
+        if (getView() != null) {
+            List<TemplateBean> templateBeanList = DataTool.getTemplateList(functionType);
+            getView().onTemplateDataCome(templateBeanList);
+        }
+    }
+}

+ 72 - 0
app/src/main/java/com/itant/shibei/ui/home/GoodsFragment.java

@@ -0,0 +1,72 @@
+package com.itant.shibei.ui.home;
+
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ImageView;
+
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.itant.shibei.R;
+import com.itant.shibei.adapter.GoodsAdapter;
+import com.itant.shibei.bean.GoodsBean;
+import com.miekir.mvp.presenter.InjectPresenter;
+import com.miekir.mvp.view.BaseMVPFragment;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ *
+ * @author 詹子聪
+ * @date 2020/7/5 22:07
+ * Description: 商品列表Fragment
+ */
+public class GoodsFragment extends BaseMVPFragment implements IGoodsView {
+
+    @InjectPresenter
+    GoodsPresenter mPresenter;
+
+    private GoodsAdapter mAdapter;
+    private RecyclerView rv_goods;
+    private List<GoodsBean> mGoodsList = new ArrayList<>();
+
+    private ImageView iv_empty;
+
+    @Override
+    public int getLayoutResId() {
+        return R.layout.fragment_home_goods;
+    }
+
+    @Override
+    public void onCreateViewFinished(@Nullable Bundle savedInstanceState) {
+        super.onCreateViewFinished(savedInstanceState);
+
+        iv_empty = rootView.findViewById(R.id.iv_empty);
+        rv_goods = rootView.findViewById(R.id.rv_goods);
+        // 必须要设置LayoutManager,否则RecyclerView不知道要使用什么布局,从而在界面上不显示
+        LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false);
+        rv_goods.setLayoutManager(layoutManager);
+        mAdapter = new GoodsAdapter(getActivity(), R.layout.item_goods, mGoodsList);
+        rv_goods.setAdapter(mAdapter);
+
+        // 获取数据
+        mPresenter.getGoodsData();
+    }
+
+    @Override
+    public void onGoodsDataCome(List<GoodsBean> goodsList) {
+        // todo 分页或者刷新
+        mGoodsList.clear();
+        mGoodsList.addAll(goodsList);
+        mAdapter.notifyDataSetChanged();
+        if (mGoodsList.size() == 0) {
+            iv_empty.setVisibility(View.VISIBLE);
+        } else {
+            iv_empty.setVisibility(View.GONE);
+        }
+
+    }
+}

+ 25 - 0
app/src/main/java/com/itant/shibei/ui/home/GoodsPresenter.java

@@ -0,0 +1,25 @@
+package com.itant.shibei.ui.home;
+
+import com.itant.shibei.bean.GoodsBean;
+import com.itant.shibei.tool.DataTool;
+import com.miekir.mvp.presenter.BasePresenter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Copyright (C), 2019-2020, Genlot
+ *
+ * @author 詹子聪
+ * @date 2020/7/9 20:54
+ * Description: 商品的相关数据接口处理
+ */
+public class GoodsPresenter extends BasePresenter<IGoodsView> {
+
+    public void getGoodsData() {
+        List<GoodsBean> goodsList = DataTool.getGoodsList();
+        if (getView() != null) {
+            getView().onGoodsDataCome(goodsList);
+        }
+    }
+}

+ 52 - 0
app/src/main/java/com/itant/shibei/ui/home/HomeFragment.java

@@ -0,0 +1,52 @@
+package com.itant.shibei.ui.home;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
+import androidx.lifecycle.ViewModelProviders;
+import androidx.viewpager.widget.ViewPager;
+
+import com.flyco.tablayout.SlidingTabLayout;
+import com.itant.shibei.R;
+import com.miekir.common.adapter.TabFragmentAdapter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class HomeFragment extends Fragment implements View.OnClickListener {
+
+
+    @Override
+    public View onCreateView(@NonNull LayoutInflater inflater,
+                             ViewGroup container, Bundle savedInstanceState) {
+        View root = inflater.inflate(R.layout.fragment_home, container, false);
+
+        String[] titles = {"推荐", "科技", "生活", "网络"};
+        List<Fragment> fragments = new ArrayList<>();
+        fragments.add(new GoodsFragment());
+        fragments.add(new GoodsFragment());
+        fragments.add(new GoodsFragment());
+        fragments.add(new GoodsFragment());
+
+        ViewPager vp_home = root.findViewById(R.id.vp_home);
+        TabFragmentAdapter adapter = new TabFragmentAdapter(getChildFragmentManager(), fragments);
+        vp_home.setAdapter(adapter);
+        vp_home.setOffscreenPageLimit(titles.length);
+        //vp_home.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
+
+        SlidingTabLayout stl_home = root.findViewById(R.id.stl_home);
+        stl_home.setViewPager(vp_home, titles);
+
+        root.findViewById(R.id.rl_search).setOnClickListener(this);
+        return root;
+    }
+
+    @Override
+    public void onClick(View v) {
+
+    }
+}

+ 17 - 0
app/src/main/java/com/itant/shibei/ui/home/IGoodsView.java

@@ -0,0 +1,17 @@
+package com.itant.shibei.ui.home;
+
+import com.itant.shibei.bean.GoodsBean;
+import com.miekir.mvp.view.IView;
+
+import java.util.List;
+
+/**
+ * Copyright (C), 2019-2020, Genlot
+ *
+ * @author 詹子聪
+ * @date 2020/7/9 20:52
+ * Description: 商品的View回调
+ */
+public interface IGoodsView extends IView {
+    void onGoodsDataCome(List<GoodsBean> goodsList);
+}

+ 37 - 0
app/src/main/java/com/itant/shibei/ui/mine/AboutActivity.java

@@ -0,0 +1,37 @@
+package com.itant.shibei.ui.mine;
+
+import android.os.Bundle;
+import android.widget.TextView;
+
+import androidx.annotation.Nullable;
+
+import com.itant.shibei.R;
+import com.itant.shibei.base.BaseShiBeiActivity;
+import com.itant.shibei.tool.SystemTool;
+
+/**
+ *
+ *
+ * @author 詹子聪
+ * @date 2020/6/18 16:48
+ * Description: 关于界面
+ * todo 点击版本号检查更新
+ */
+public class AboutActivity extends BaseShiBeiActivity {
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setTitle("关于");
+    }
+
+    @Override
+    public int getLayoutID() {
+        return R.layout.activity_about;
+    }
+
+    @Override
+    public void initViews(Bundle savedInstanceState) {
+        TextView tv_title = findViewById(R.id.tv_title);
+        tv_title.setText(" 拾贝 v" + SystemTool.getVersionName(this));
+    }
+}

+ 55 - 0
app/src/main/java/com/itant/shibei/ui/mine/MineFragment.java

@@ -0,0 +1,55 @@
+package com.itant.shibei.ui.mine;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
+
+import com.itant.shibei.R;
+import com.itant.shibei.tool.SystemTool;
+import com.itant.shibei.ui.mine.login.UserInfoManager;
+import com.itant.shibei.ui.mine.login.LoginActivity;
+
+public class MineFragment extends Fragment implements View.OnClickListener {
+
+
+    @Override
+    public View onCreateView(@NonNull LayoutInflater inflater,
+                             ViewGroup container, Bundle savedInstanceState) {
+        View root = inflater.inflate(R.layout.fragment_mine, container, false);
+        root.findViewById(R.id.ll_about).setOnClickListener(this);
+        root.findViewById(R.id.ll_user).setOnClickListener(this);
+        root.findViewById(R.id.ll_feedback).setOnClickListener(this);
+        return root;
+
+    }
+
+    @Override
+    public void onClick(View v) {
+        switch (v.getId()) {
+            case R.id.ll_about:
+                startActivity(new Intent(getActivity(), AboutActivity.class));
+                break;
+
+            case R.id.ll_user:
+                if (!UserInfoManager.getInstance().isLogin()) {
+                    // 未登录,跳转登录
+                    startActivity(new Intent(getActivity(), LoginActivity.class));
+                } else {
+                    // 退出登录对话框
+                }
+                break;
+
+            case R.id.ll_feedback:
+                SystemTool.sendEmail(getActivity());
+                break;
+
+            default:
+                break;
+        }
+    }
+}

+ 74 - 0
app/src/main/java/com/itant/shibei/ui/mine/login/LoginActivity.java

@@ -0,0 +1,74 @@
+package com.itant.shibei.ui.mine.login;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.itant.shibei.R;
+import com.itant.shibei.base.BaseShiBeiActivity;
+import com.itant.shibei.ui.mine.login.forget.ForgetActivity;
+import com.itant.shibei.ui.mine.login.register.RegisterActivity;
+import com.miekir.common.utils.ViewTool;
+import com.miekir.mvp.view.BaseMVPActivity;
+
+/**
+ * @author 詹子聪
+ * @date 2020/6/18 16:48
+ * Description: 登录界面
+ */
+public class LoginActivity extends BaseShiBeiActivity implements View.OnClickListener {
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+    }
+
+    @Override
+    public int getLayoutID() {
+        return R.layout.activity_login;
+    }
+
+    @Override
+    public void initViews(Bundle savedInstanceState) {
+        setTitle("登录");
+        //setOnDoneListener(this);
+        ViewTool.setOnClickListener(this, new int[]{R.id.tv_register, R.id.tv_forget}, this);
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        getMenuInflater().inflate(R.menu.menu_done, menu);
+        return super.onCreateOptionsMenu(menu);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
+        switch (item.getItemId()) {
+            case R.id.action_done:
+                finish();
+                break;
+            default:
+                break;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    @Override
+    public void onClick(View v) {
+        switch (v.getId()) {
+            case R.id.tv_register:
+                startActivity(new Intent(this, RegisterActivity.class));
+                break;
+            case R.id.tv_forget:
+                startActivity(new Intent(this, ForgetActivity.class));
+                break;
+            default:
+                break;
+        }
+    }
+}

+ 37 - 0
app/src/main/java/com/itant/shibei/ui/mine/login/UserInfoManager.java

@@ -0,0 +1,37 @@
+package com.itant.shibei.ui.mine.login;
+
+/**
+ *
+ *
+ * @author 詹子聪
+ * @date 2020/6/27 20:40
+ * Description: 用户信息
+ */
+public class UserInfoManager {
+    private static volatile UserInfoManager userInfoManager;
+    private UserInfoManager() {}
+
+    private boolean isLogin;
+
+    public static UserInfoManager getInstance() {
+        if (userInfoManager == null) {
+            init();
+        }
+
+        return userInfoManager;
+    }
+
+    private static synchronized void init() {
+        if (userInfoManager == null) {
+            userInfoManager = new UserInfoManager();
+        }
+    }
+
+    public boolean isLogin() {
+        return isLogin;
+    }
+
+    public void setLogin(boolean login) {
+        isLogin = login;
+    }
+}

+ 63 - 0
app/src/main/java/com/itant/shibei/ui/mine/login/forget/ForgetActivity.java

@@ -0,0 +1,63 @@
+package com.itant.shibei.ui.mine.login.forget;
+
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.itant.shibei.R;
+import com.itant.shibei.base.BaseShiBeiActivity;
+
+/**
+ * @author 詹子聪
+ * @date 2020/6/18 16:48
+ * Description: 登录界面
+ */
+public class ForgetActivity extends BaseShiBeiActivity implements View.OnClickListener {
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+    }
+
+    @Override
+    public int getLayoutID() {
+        return R.layout.activity_forget;
+    }
+
+    @Override
+    public void initViews(Bundle savedInstanceState) {
+        setTitle("重置密码");
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        getMenuInflater().inflate(R.menu.menu_done, menu);
+        //MenuItem item = menu.findItem(R.id.action_done);
+        //item.setTitle("重置完成");
+        return super.onCreateOptionsMenu(menu);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
+        switch (item.getItemId()) {
+            case R.id.action_done:
+                finish();
+                break;
+            default:
+                break;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    @Override
+    public void onClick(View v) {
+        switch (v.getId()) {
+            default:
+                break;
+        }
+    }
+}

+ 63 - 0
app/src/main/java/com/itant/shibei/ui/mine/login/register/RegisterActivity.java

@@ -0,0 +1,63 @@
+package com.itant.shibei.ui.mine.login.register;
+
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.itant.shibei.R;
+import com.itant.shibei.base.BaseShiBeiActivity;
+
+/**
+ * @author 詹子聪
+ * @date 2020/6/18 16:48
+ * Description: 登录界面
+ */
+public class RegisterActivity extends BaseShiBeiActivity implements View.OnClickListener {
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+    }
+
+    @Override
+    public int getLayoutID() {
+        return R.layout.activity_register;
+    }
+
+    @Override
+    public void initViews(Bundle savedInstanceState) {
+        setTitle("注册");
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        getMenuInflater().inflate(R.menu.menu_done, menu);
+        //MenuItem item = menu.findItem(R.id.action_done);
+        //item.setTitle("完成注册");
+        return super.onCreateOptionsMenu(menu);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
+        switch (item.getItemId()) {
+            case R.id.action_done:
+                finish();
+                break;
+            default:
+                break;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    @Override
+    public void onClick(View v) {
+        switch (v.getId()) {
+            default:
+                break;
+        }
+    }
+}

+ 3 - 0
app/src/main/res/anim/nav_default_enter_anim.xml

@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+</set>

+ 3 - 0
app/src/main/res/anim/nav_default_exit_anim.xml

@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+</set>

+ 3 - 0
app/src/main/res/anim/nav_default_pop_enter_anim.xml

@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+</set>

+ 3 - 0
app/src/main/res/anim/nav_default_pop_exit_anim.xml

@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+</set>

+ 6 - 0
app/src/main/res/color/selector_edittext_outline.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="@color/colorPrimary" android:state_focused="true" />
+    <item android:color="@color/colorPrimaryDark" />  <!-- unfocused -->
+</selector>

+ 5 - 0
app/src/main/res/color/selector_nav_item_color.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_checked="true" android:color="@color/black_dark" />
+    <item android:state_checked="false" android:color="@color/gray_normal"/>
+</selector>

+ 7 - 0
app/src/main/res/drawable-v21/ripple_click.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ripple
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:color="@color/gray_divider_light_transparent"
+    tools:ignore="NewApi" />
+<!--上面就是点击时的ripple颜色-->

+ 6 - 0
app/src/main/res/drawable-v21/selectable_item_background.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <!--<item android:state_pressed="false" android:drawable="@android:color/transparent" />
+    <item android:drawable="@color/gray_divider_light_transparent" />-->
+    <item android:drawable="@drawable/ripple_click" />
+</selector>

File diff suppressed because it is too large
+ 14 - 0
app/src/main/res/drawable/ic_computer.xml


+ 15 - 0
app/src/main/res/drawable/ic_done.xml

@@ -0,0 +1,15 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="1024.0"
+        android:viewportHeight="1024.0">
+    <!--<path
+        android:fillColor="#444444"
+        android:pathData="M793.6 614.4H230.4c-15.36 0-25.6-10.24-25.6-25.6s10.24-25.6 25.6-25.6h486.4l-143.36-107.52c-10.24-7.68-12.8-25.6-5.12-35.84s25.6-12.8 35.84-5.12l204.8 153.6c7.68 7.68 12.8 17.92 7.68 28.16-2.56 10.24-12.8 17.92-23.04 17.92z"/>-->
+    <!--<path
+        android:fillColor="#444444"
+        android:pathData="M9,16.2L4.8,12l-1.4,1.4L9,19 21,7l-1.4,-1.4L9,16.2z"/>-->
+    <path
+        android:fillColor="#11B667"
+        android:pathData="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64z m294.2 307.5L489.4 688.3c-25 25-65.5 25-90.5 0l-181-181c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L399 597.8l45.3 45.3 45.3-45.3 271.5-271.5c12.5-12.5 32.8-12.5 45.3 0 12.3 12.5 12.3 32.8-0.2 45.2z"/>
+</vector>

File diff suppressed because it is too large
+ 10 - 0
app/src/main/res/drawable/ic_launcher.xml


File diff suppressed because it is too large
+ 11 - 0
app/src/main/res/drawable/ic_logo.xml


+ 9 - 0
app/src/main/res/drawable/ic_mine_about.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#3C4043"
+        android:pathData="M11,17h2v-6h-2v6zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2L13,7h-2v2z"/>
+</vector>

File diff suppressed because it is too large
+ 13 - 0
app/src/main/res/drawable/ic_mine_cash.xml


+ 9 - 0
app/src/main/res/drawable/ic_mine_feedback.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#3C4043"
+        android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
+</vector>

+ 9 - 0
app/src/main/res/drawable/ic_mine_mall.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#3C4043"
+        android:pathData="M19,6h-2c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6L5,6c-1.1,0 -1.99,0.9 -1.99,2L3,20c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,8c0,-1.1 -0.9,-2 -2,-2zM12,3c1.66,0 3,1.34 3,3L9,6c0,-1.66 1.34,-3 3,-3zM12,13c-2.76,0 -5,-2.24 -5,-5h2c0,1.66 1.34,3 3,3s3,-1.34 3,-3h2c0,2.76 -2.24,5 -5,5z"/>
+</vector>

File diff suppressed because it is too large
+ 16 - 0
app/src/main/res/drawable/ic_mine_money.xml


+ 9 - 0
app/src/main/res/drawable/ic_mine_star.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#3C4043"
+        android:pathData="M22,9.24l-7.19,-0.62L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21 12,17.27 18.18,21l-1.63,-7.03L22,9.24zM12,15.4l-3.76,2.27 1,-4.28 -3.32,-2.88 4.38,-0.38L12,6.1l1.71,4.04 4.38,0.38 -3.32,2.88 1,4.28L12,15.4z"/>
+</vector>

+ 9 - 0
app/src/main/res/drawable/ic_mine_update.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#3C4043"
+        android:pathData="M21,10.12h-6.78l2.74,-2.82c-2.73,-2.7 -7.15,-2.8 -9.88,-0.1 -2.73,2.71 -2.73,7.08 0,9.79 2.73,2.71 7.15,2.71 9.88,0C18.32,15.65 19,14.08 19,12.1h2c0,1.98 -0.88,4.55 -2.64,6.29 -3.51,3.48 -9.21,3.48 -12.72,0 -3.5,-3.47 -3.53,-9.11 -0.02,-12.58 3.51,-3.47 9.14,-3.47 12.65,0L21,3v7.12zM12.5,8v4.25l3.5,2.08 -0.72,1.21L11,13V8h1.5z"/>
+</vector>

File diff suppressed because it is too large
+ 13 - 0
app/src/main/res/drawable/ic_mine_upload.xml


File diff suppressed because it is too large
+ 12 - 0
app/src/main/res/drawable/ic_nav_fire.xml


File diff suppressed because it is too large
+ 15 - 0
app/src/main/res/drawable/ic_nav_game.xml


File diff suppressed because it is too large
+ 9 - 0
app/src/main/res/drawable/ic_nav_mall.xml


+ 9 - 0
app/src/main/res/drawable/ic_nav_mine.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
+</vector>

+ 10 - 0
app/src/main/res/drawable/ic_nav_template.xml

@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="1024.0"
+    android:viewportHeight="1024.0">
+
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M426.666667 170.666667v682.666666H213.333333a42.666667 42.666667 0 0 1-42.666666-42.666666V213.333333a42.666667 42.666667 0 0 1 42.666666-42.666666h213.333334z m426.666666 426.666666v213.333334a42.666667 42.666667 0 0 1-42.666666 42.666666h-341.333334v-256h384zM810.666667 170.666667a42.666667 42.666667 0 0 1 42.666666 42.666666v341.333334h-384V170.666667h341.333334z" />
+</vector>

+ 9 - 0
app/src/main/res/drawable/ic_search.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#444444"
+        android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>
+</vector>

+ 80 - 0
app/src/main/res/drawable/layer_shadow.xml

@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <!-- Drop Shadow Stack -->
+    <item>
+        <shape>
+            <padding
+                android:bottom="1dp"
+                android:left="1dp"
+                android:right="1dp"
+                android:top="1dp" />
+
+            <solid android:color="#00CCCCCC" />
+
+            <corners android:radius="3dp" />
+        </shape>
+    </item>
+    <item>
+        <shape>
+            <padding
+                android:bottom="1dp"
+                android:left="1dp"
+                android:right="1dp"
+                android:top="1dp" />
+
+            <solid android:color="#10CCCCCC" />
+
+            <corners android:radius="3dp" />
+        </shape>
+    </item>
+    <item>
+        <shape>
+            <padding
+                android:bottom="1dp"
+                android:left="1dp"
+                android:right="1dp"
+                android:top="1dp" />
+
+            <solid android:color="#20CCCCCC" />
+
+            <corners android:radius="3dp" />
+        </shape>
+    </item>
+    <item>
+        <shape>
+            <padding
+                android:bottom="1dp"
+                android:left="1dp"
+                android:right="1dp"
+                android:top="1dp" />
+
+            <solid android:color="#30CCCCCC" />
+
+            <corners android:radius="3dp" />
+        </shape>
+    </item>
+    <item>
+        <shape>
+            <padding
+                android:bottom="1dp"
+                android:left="1dp"
+                android:right="1dp"
+                android:top="1dp" />
+
+            <solid android:color="#50CCCCCC" />
+
+            <corners android:radius="3dp" />
+        </shape>
+    </item>
+
+    <!-- Background -->
+    <item>
+        <shape>
+            <solid android:color="@android:color/white" />
+
+            <corners android:radius="3dp" />
+        </shape>
+    </item>
+
+</layer-list>

+ 21 - 0
app/src/main/res/drawable/ripple_oval.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ripple
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:color="@color/grayDark"
+    tools:ignore="NewApi">
+    <!--<item android:id="@android:id/mask">
+        <shape android:shape="oval">
+
+            <solid android:color="@color/gray_divider_light_transparent" />
+        </shape>
+    </item>-->
+    <item>
+        <shape android:shape="oval">
+            <size android:width="100dp" android:height="100dp"/>
+
+            <solid android:color="@color/colorPrimary" />
+        </shape>
+    </item>
+</ripple>
+<!--上面就是点击时的ripple颜色-->

+ 5 - 0
app/src/main/res/drawable/selectable_item_background.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="false" android:drawable="@android:color/transparent" />
+    <item android:drawable="@color/gray_divider_light_transparent" />
+</selector>

+ 22 - 0
app/src/main/res/drawable/selector_btn.xml

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true">
+        <shape android:shape="rectangle">
+            <corners android:radius="@dimen/margin_ss"/>
+            <solid android:color="@color/black_text"/>
+        </shape>
+    </item>
+
+    <item android:state_enabled="false">
+        <shape android:shape="rectangle">
+            <corners android:radius="@dimen/margin_ss"/>
+            <solid android:color="@color/black_text"/>
+        </shape>
+    </item>
+    <item>
+        <shape android:shape="rectangle">
+            <corners android:radius="@dimen/margin_ss"/>
+            <solid android:color="@color/black_light"/>
+        </shape>
+    </item>
+</selector>

+ 6 - 0
app/src/main/res/drawable/shape_black_radius_transparent.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <corners android:radius="@dimen/margin_ss"/>
+    <solid android:color="@color/black_light_transparent"/>
+</shape>

+ 10 - 0
app/src/main/res/drawable/shape_black_stroke_right.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <corners
+        android:bottomRightRadius="@dimen/margin_sss"
+        android:topRightRadius="@dimen/margin_sss" />
+    <stroke
+        android:width="@dimen/padding_slim"
+        android:color="@color/black_light_transparent" />
+</shape>

+ 8 - 0
app/src/main/res/drawable/shape_black_tag_gradient.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <corners android:bottomLeftRadius="@dimen/margin_sss"
+        android:topLeftRadius="@dimen/margin_sss"/>
+
+    <solid android:color="@color/black_light_transparent"/>
+</shape>

+ 6 - 0
app/src/main/res/drawable/shape_circle.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="oval">
+    <stroke android:color="@color/black_theme" android:width="1dp"/>
+    <solid android:color="@color/white_slight"/>
+</shape>

+ 6 - 0
app/src/main/res/drawable/shape_gray_stroke_s.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <solid android:color="@color/transparent" />
+    <stroke android:color="@color/gray_divider_1" android:width="@dimen/width_stroke" />
+</shape>

+ 7 - 0
app/src/main/res/drawable/shape_gray_stroke_s_radius.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <solid android:color="@color/transparent" />
+    <stroke android:color="@color/gray_text" android:width="@dimen/height_divider_micro" />
+    <corners android:radius="@dimen/radius_s"/>
+</shape>

+ 6 - 0
app/src/main/res/drawable/shape_gray_stroke_solid.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <solid android:color="@color/gray_divider_light" />
+    <stroke android:color="@color/black_theme" android:width="@dimen/radius_indicator" />
+</shape>

+ 10 - 0
app/src/main/res/drawable/shape_gray_tag.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <corners android:radius="@dimen/activity_horizontal_margin_s"/>
+
+    <solid android:color="@color/gray"/>
+    <!--<gradient
+        android:endColor="@color/grayDark"
+        android:startColor="@color/jd_black_bg_tag" />-->
+</shape>

+ 10 - 0
app/src/main/res/drawable/shape_purple_stroke_right.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <corners
+        android:bottomRightRadius="@dimen/margin_sss"
+        android:topRightRadius="@dimen/margin_sss" />
+    <stroke
+        android:width="@dimen/padding_slim"
+        android:color="@color/jd_purple_bg_light" />
+</shape>

+ 9 - 0
app/src/main/res/drawable/shape_purple_tag_gradient.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <corners android:bottomLeftRadius="@dimen/margin_sss"
+        android:topLeftRadius="@dimen/margin_sss"/>
+    <gradient
+        android:endColor="@color/jd_purple_bg_light"
+        android:startColor="@color/jd_purple_bg_dark" />
+</shape>

+ 7 - 0
app/src/main/res/drawable/shape_radius.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <corners android:radius="@dimen/activity_horizontal_margin_ss"/>
+    <stroke android:color="@color/white" android:width="1dp"/>
+    <solid android:color="@color/gray_divider_light"/>
+</shape>

+ 8 - 0
app/src/main/res/drawable/shape_red_tag_gradient.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <corners android:radius="@dimen/margin_sss" />
+    <gradient
+        android:endColor="@color/jd_red_bg_tag_to"
+        android:startColor="@color/jd_red_bg_tag_from" />
+</shape>

+ 8 - 0
app/src/main/res/drawable/shape_shadow.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <gradient
+        android:startColor="@color/gray_divider_1"
+        android:endColor="@color/transparent"
+        android:angle="270">
+    </gradient>
+</shape>

+ 0 - 0
app/src/main/res/layout/activity_about.xml


Some files were not shown because too many files changed in this diff