tips = new ArrayList<>();
92 | tips.add("AndroidNexus");
93 | tips.add("EasyToForget");
94 | tips.add("zhiye.wei@gmail.com");
95 |
96 | timer = new CountDownTimer(3000000, 5000) {
97 | @Override
98 | public void onTick(long millisUntilFinished) {
99 | tvSearchTips.setText(tips.get(new Random().nextInt(2)));
100 | }
101 |
102 | @Override
103 | public void onFinish() {
104 |
105 | }
106 | };
107 | }
108 |
109 | @Override
110 | protected void onResume() {
111 | super.onResume();
112 | }
113 |
114 | @Override
115 | protected void onStart() {
116 | super.onStart();
117 | timer.start();
118 | }
119 |
120 | @Override
121 | protected void onStop() {
122 | super.onStop();
123 | timer.cancel();
124 | }
125 |
126 | @Override
127 | public void onBackPressed() {
128 | moveTaskToBack(false);
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_detail.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
13 |
14 |
15 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
31 |
32 |
33 |
38 |
39 |
51 |
52 |
56 |
57 |
69 |
70 |
74 |
75 |
87 |
88 |
89 |
99 |
100 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
120 |
121 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/app/src/main/java/com/smile/taobaodemo/widget/RecycleBin.java:
--------------------------------------------------------------------------------
1 | package com.smile.taobaodemo.widget;
2 |
3 | import android.os.Build;
4 | import android.util.SparseArray;
5 | import android.view.View;
6 |
7 | /**
8 | * The RecycleBin facilitates reuse of views across layouts. The RecycleBin has two levels of
9 | * storage: ActiveViews and ScrapViews. ActiveViews are those views which were onscreen at the
10 | * start of a layout. By construction, they are displaying current information. At the end of
11 | * layout, all views in ActiveViews are demoted to ScrapViews. ScrapViews are old views that
12 | * could potentially be used by the adapter to avoid allocating views unnecessarily.
13 | *
14 | * This class was taken from Android's implementation of {@link android.widget.AbsListView} which
15 | * is copyrighted 2006 The Android Open Source Project.
16 | */
17 | public class RecycleBin {
18 | /**
19 | * Views that were on screen at the start of layout. This array is populated at the start of
20 | * layout, and at the end of layout all view in activeViews are moved to scrapViews.
21 | * Views in activeViews represent a contiguous range of Views, with position of the first
22 | * view store in mFirstActivePosition.
23 | */
24 | private View[] activeViews = new View[0];
25 | private int[] activeViewTypes = new int[0];
26 |
27 | /** Unsorted views that can be used by the adapter as a convert view. */
28 | private SparseArray[] scrapViews;
29 |
30 | private int viewTypeCount;
31 |
32 | private SparseArray currentScrapViews;
33 |
34 | public void setViewTypeCount(int viewTypeCount) {
35 | if (viewTypeCount < 1) {
36 | throw new IllegalArgumentException("Can't have a viewTypeCount < 1");
37 | }
38 | //noinspection unchecked
39 | SparseArray[] scrapViews = new SparseArray[viewTypeCount];
40 | for (int i = 0; i < viewTypeCount; i++) {
41 | scrapViews[i] = new SparseArray();
42 | }
43 | this.viewTypeCount = viewTypeCount;
44 | currentScrapViews = scrapViews[0];
45 | this.scrapViews = scrapViews;
46 | }
47 |
48 | protected boolean shouldRecycleViewType(int viewType) {
49 | return viewType >= 0;
50 | }
51 |
52 | /** @return A view from the ScrapViews collection. These are unordered. */
53 | public View getScrapView(int position, int viewType) {
54 | if (viewTypeCount == 1) {
55 | return retrieveFromScrap(currentScrapViews, position);
56 | } else if (viewType >= 0 && viewType < scrapViews.length) {
57 | return retrieveFromScrap(scrapViews[viewType], position);
58 | }
59 | return null;
60 | }
61 |
62 | /**
63 | * Put a view into the ScrapViews list. These views are unordered.
64 | *
65 | * @param scrap The view to add
66 | */
67 | public void addScrapView(View scrap, int position, int viewType) {
68 | if (viewTypeCount == 1) {
69 | currentScrapViews.put(position, scrap);
70 | } else {
71 | scrapViews[viewType].put(position, scrap);
72 | }
73 |
74 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
75 | scrap.setAccessibilityDelegate(null);
76 | }
77 | }
78 |
79 | /** Move all views remaining in activeViews to scrapViews. */
80 | public void scrapActiveViews() {
81 | final View[] activeViews = this.activeViews;
82 | final int[] activeViewTypes = this.activeViewTypes;
83 | final boolean multipleScraps = viewTypeCount > 1;
84 |
85 | SparseArray scrapViews = currentScrapViews;
86 | final int count = activeViews.length;
87 | for (int i = count - 1; i >= 0; i--) {
88 | final View victim = activeViews[i];
89 | if (victim != null) {
90 | int whichScrap = activeViewTypes[i];
91 |
92 | activeViews[i] = null;
93 | activeViewTypes[i] = -1;
94 |
95 | if (!shouldRecycleViewType(whichScrap)) {
96 | continue;
97 | }
98 |
99 | if (multipleScraps) {
100 | scrapViews = this.scrapViews[whichScrap];
101 | }
102 | scrapViews.put(i, victim);
103 |
104 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
105 | victim.setAccessibilityDelegate(null);
106 | }
107 | }
108 | }
109 |
110 | pruneScrapViews();
111 | }
112 |
113 | /**
114 | * Makes sure that the size of scrapViews does not exceed the size of activeViews.
115 | * (This can happen if an adapter does not recycle its views).
116 | */
117 | private void pruneScrapViews() {
118 | final int maxViews = activeViews.length;
119 | final int viewTypeCount = this.viewTypeCount;
120 | final SparseArray[] scrapViews = this.scrapViews;
121 | for (int i = 0; i < viewTypeCount; ++i) {
122 | final SparseArray scrapPile = scrapViews[i];
123 | int size = scrapPile.size();
124 | final int extras = size - maxViews;
125 | size--;
126 | for (int j = 0; j < extras; j++) {
127 | scrapPile.remove(scrapPile.keyAt(size--));
128 | }
129 | }
130 | }
131 |
132 | static View retrieveFromScrap(SparseArray scrapViews, int position) {
133 | int size = scrapViews.size();
134 | if (size > 0) {
135 | // See if we still have a view for this position.
136 | for (int i = 0; i < size; i++) {
137 | int fromPosition = scrapViews.keyAt(i);
138 | View view = scrapViews.get(fromPosition);
139 | if (fromPosition == position) {
140 | scrapViews.remove(fromPosition);
141 | return view;
142 | }
143 | }
144 | int index = size - 1;
145 | View r = scrapViews.valueAt(index);
146 | scrapViews.remove(scrapViews.keyAt(index));
147 | return r;
148 | } else {
149 | return null;
150 | }
151 | }
152 | }
153 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_navigation_home_category.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
12 |
13 |
24 |
25 |
36 |
37 |
48 |
49 |
60 |
61 |
72 |
73 |
74 |
75 |
82 |
83 |
94 |
95 |
106 |
107 |
118 |
119 |
130 |
131 |
142 |
143 |
144 |
145 |
--------------------------------------------------------------------------------
/app/src/main/java/com/smile/taobaodemo/ui/fragment/NavHomeFragment.java:
--------------------------------------------------------------------------------
1 | package com.smile.taobaodemo.ui.fragment;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.os.Bundle;
7 | import android.support.v4.app.Fragment;
8 | import android.support.v4.widget.SwipeRefreshLayout;
9 | import android.support.v7.widget.GridLayoutManager;
10 | import android.view.LayoutInflater;
11 | import android.view.View;
12 | import android.view.ViewGroup;
13 |
14 | import com.smile.taobaodemo.R;
15 | import com.smile.taobaodemo.base.BundleKey;
16 | import com.smile.taobaodemo.base.Type;
17 | import com.smile.taobaodemo.model.entity.HomeBase;
18 | import com.smile.taobaodemo.model.entity.HomeBottom;
19 | import com.smile.taobaodemo.model.entity.HomeTop;
20 | import com.smile.taobaodemo.presenter.HomePresenter;
21 | import com.smile.taobaodemo.ui.activity.DetailActivity;
22 | import com.smile.taobaodemo.ui.adapter.HomeAdapter;
23 | import com.smile.taobaodemo.contract.HomeContract;
24 | import com.smile.taobaodemo.utils.ToastUtil;
25 | import com.smile.taobaodemo.widget.LoadMoreRecyclerView;
26 |
27 | import java.util.ArrayList;
28 | import java.util.List;
29 |
30 | import butterknife.BindView;
31 | import butterknife.ButterKnife;
32 |
33 | /**
34 | * @author Smile Wei
35 | * @since 2017/03/01.
36 | */
37 |
38 | public class NavHomeFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener,
39 | LoadMoreRecyclerView.OnLoadMoreListener, HomeContract.View, HomeAdapter.OnItemClickListener {
40 | private final static int HOME_TOP = 1;
41 | private final static int HOME_BOTTOM = 2;
42 | @BindView(R.id.refresh_layout)
43 | SwipeRefreshLayout refreshLayout;
44 | @BindView(R.id.recycler_view)
45 | LoadMoreRecyclerView recyclerView;
46 | private Context context;
47 | private Activity activity;
48 |
49 | private List list = new ArrayList<>();
50 |
51 | private HomeAdapter adapter;
52 | private HomePresenter presenter;
53 | private int page = 1;
54 | private int pageSize = 10;
55 | private HomeBase footerItem = new HomeBase();
56 |
57 | public static NavHomeFragment newInstance() {
58 | NavHomeFragment fragment = new NavHomeFragment();
59 | Bundle args = new Bundle();
60 | fragment.setArguments(args);
61 | return fragment;
62 | }
63 |
64 | @Override
65 | public void onCreate(Bundle savedInstanceState) {
66 | super.onCreate(savedInstanceState);
67 | }
68 |
69 | @Override
70 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
71 | Bundle savedInstanceState) {
72 | View view = inflater.inflate(R.layout.fragment_navigation_home, container, false);
73 | ButterKnife.bind(this, view);
74 |
75 | activity = getActivity();
76 | context = activity.getApplicationContext();
77 |
78 | presenter = new HomePresenter();
79 | presenter.init(this, context);
80 | return view;
81 | }
82 |
83 | @Override
84 | public void initView() {
85 | refreshLayout.setColorSchemeResources(R.color.font_orange_color);
86 | refreshLayout.setOnRefreshListener(this);
87 | int spanCount = getResources().getInteger(R.integer.grid_span_count);
88 |
89 | GridLayoutManager layoutManager = new GridLayoutManager(activity, spanCount);
90 | recyclerView.setLayoutManager(layoutManager);
91 | adapter = new HomeAdapter(context, activity, list);
92 | adapter.setOnItemClickListener(this);
93 | layoutManager.setSpanSizeLookup(adapter.getSpanSizeLookup());
94 | recyclerView.setAdapter(adapter);
95 | recyclerView.setOnLoadMoreListener(this);
96 |
97 | footerItem.setType(Type.TYPE_FOOTER_LOAD);
98 | footerItem.setSpanCount(spanCount);
99 | presenter.start(HOME_TOP);
100 | }
101 |
102 | @Override
103 | public void onRefresh() {
104 | setRefreshLoading(false);
105 | presenter.start(HOME_TOP);
106 | page = 1;
107 | }
108 |
109 | @Override
110 | public void onLoadMore() {
111 | setRefreshLoading(true);
112 | page++;
113 | presenter.start(HOME_BOTTOM, page, pageSize);
114 | }
115 |
116 | //轮播、分类、头条、直播回调
117 | @Override
118 | public void show(HomeTop bean) {
119 | list.clear();
120 | adapter.setLoopList(bean.getCarousel());
121 | adapter.setHeadlineList(bean.getHeadlines());
122 |
123 | list.addAll(bean.getList());
124 | list.add(footerItem);
125 | adapter.notifyDataSetChanged();
126 |
127 | presenter.start(HOME_BOTTOM, page, pageSize);
128 | }
129 |
130 |
131 | //猜你喜欢模块回调
132 | @Override
133 | public void show(HomeBottom bean) {
134 | recyclerView.setPage(page, bean.getTotalPage());
135 | footerItem.setType(page < bean.getTotalPage() ? Type.TYPE_FOOTER_LOAD : Type.TYPE_FOOTER_FULL);
136 | list.addAll(list.size() - 1, bean.getData());
137 | adapter.notifyDataSetChanged();
138 | setRefreshLoading(false);
139 | }
140 |
141 | @Override
142 | public void loading() {
143 |
144 | }
145 |
146 | @Override
147 | public void networkError() {
148 | setRefreshLoading(false);
149 | ToastUtil.showShortToast(context, R.string.toast_network_error);
150 |
151 | }
152 |
153 | @Override
154 | public void error(String msg) {
155 | setRefreshLoading(false);
156 | ToastUtil.showShortToast(context, msg);
157 | }
158 |
159 | @Override
160 | public void showFailed(String msg) {
161 | setRefreshLoading(false);
162 | ToastUtil.showShortToast(context, msg);
163 | }
164 |
165 | /**
166 | * 设置刷新和加载更多的状态
167 | *
168 | * @param isLoading 加载更多状态
169 | */
170 | private void setRefreshLoading(boolean isLoading) {
171 | if (!isLoading) {
172 | recyclerView.setLoading(false);
173 | refreshLayout.setRefreshing(false);
174 | }
175 | }
176 |
177 | @Override
178 | public void onItemClick(int position) {
179 | Intent intent = new Intent();
180 | intent.setClass(getActivity(), DetailActivity.class);
181 | intent.putExtra(BundleKey.PARCELABLE, list.get(position));
182 | startActivity(intent);
183 | }
184 | }
185 |
--------------------------------------------------------------------------------
/app/src/main/java/com/smile/taobaodemo/okhttp/OkHttp.java:
--------------------------------------------------------------------------------
1 | package com.smile.taobaodemo.okhttp;
2 |
3 | import android.content.Context;
4 | import android.util.Log;
5 |
6 | import java.io.File;
7 | import java.net.URLEncoder;
8 | import java.util.HashMap;
9 | import java.util.List;
10 | import java.util.Map;
11 | import java.util.concurrent.TimeUnit;
12 |
13 | import okhttp3.Call;
14 | import okhttp3.FormBody;
15 | import okhttp3.MultipartBody;
16 | import okhttp3.OkHttpClient;
17 | import okhttp3.Request;
18 | import okhttp3.RequestBody;
19 |
20 | /**
21 | * @author Smile Wei
22 | * @since 2016/8/2.
23 | */
24 | public class OkHttp {
25 | private static OkHttpClient client;
26 |
27 | private static OkHttpClient init() {
28 | synchronized (OkHttp.class) {
29 | if (client == null) {
30 | client = new OkHttpClient.Builder()
31 | .readTimeout(30, TimeUnit.SECONDS)
32 | .writeTimeout(30, TimeUnit.SECONDS)
33 | .connectTimeout(30, TimeUnit.SECONDS)
34 | .build();
35 | }
36 | }
37 | return client;
38 | }
39 |
40 | private static OkHttpClient getInstance() {
41 | return client == null ? init() : client;
42 | }
43 |
44 | /**
45 | * get方法
46 | *
47 | * @param url url
48 | * @param params 参数
49 | * @param callback 回调函数
50 | * @return call
51 | */
52 | public static Call get(Context context, String url, Map params, OkCallback callback) {
53 | return get(context, url, params, null, callback);
54 | }
55 |
56 | /**
57 | * get方法
58 | *
59 | * @param url url
60 | * @param params 参数
61 | * @param callback 回调函数
62 | * @return call
63 | */
64 | public static Call get(Context context, String url, Map params, boolean isJumpLogin, OkCallback callback) {
65 | return get(context, url, params, null, isJumpLogin, callback);
66 | }
67 |
68 |
69 | /**
70 | * get方法
71 | *
72 | * @param url url
73 | * @param params 参数
74 | * @param tag 标记位
75 | * @param callback 回调函数
76 | * @return call
77 | */
78 | public static Call get(Context context, String url, Map params, Object tag, OkCallback callback) {
79 | callback.setContext(context);
80 | String endUrl = url + "?" + encodeParameters(context, params);
81 | Log.d("url", endUrl);
82 | Request.Builder builder = new Request.Builder().url(endUrl);
83 | if (tag != null) {
84 | builder.tag(tag);
85 | }
86 | Request request = builder.build();
87 | Call call = getInstance().newCall(request);
88 | call.enqueue(callback);
89 | return call;
90 | }
91 |
92 | /**
93 | * get方法
94 | *
95 | * @param url url
96 | * @param params 参数
97 | * @param tag 标记位
98 | * @param callback 回调函数
99 | * @return call
100 | */
101 | public static Call get(Context context, String url, Map params, Object tag, boolean isJumpLogin, OkCallback callback) {
102 | callback.setContext(context);
103 | callback.setJumpLogin(isJumpLogin);
104 | String endUrl = url + "?" + encodeParameters(context, params);
105 | Log.d("url", endUrl);
106 | Request.Builder builder = new Request.Builder().url(endUrl);
107 | if (tag != null) {
108 | builder.tag(tag);
109 | }
110 | Request request = builder.build();
111 | Call call = getInstance().newCall(request);
112 | call.enqueue(callback);
113 | return call;
114 | }
115 |
116 |
117 | /**
118 | * post方法
119 | *
120 | * @param url url
121 | * @param params 参数
122 | * @param callback 回调函数
123 | * @return call
124 | */
125 | public static Call post(Context context, String url, Map params, OkCallback callback) {
126 | return post(context, url, params, null, callback);
127 | }
128 |
129 | /**
130 | * post方法
131 | *
132 | * @param url url
133 | * @param params 参数
134 | * @param tag 标记位
135 | * @param callback 回调函数
136 | * @return call
137 | */
138 | public static Call post(Context context, String url, Map params, Object tag, OkCallback callback) {
139 | callback.setContext(context);
140 | Request.Builder builder = new Request.Builder().url(url);
141 | if (tag != null) {
142 | builder.tag(tag);
143 | }
144 | FormBody.Builder formBuilder = new FormBody.Builder();
145 | if (params != null && params.size() > 0) {
146 | for (String key : params.keySet()) {
147 | formBuilder.add(key, params.get(key));
148 | }
149 | }
150 | builder.post(formBuilder.build());
151 |
152 | Request request = builder.build();
153 | Call call = getInstance().newCall(request);
154 | call.enqueue(callback);
155 | return call;
156 | }
157 |
158 |
159 | /**
160 | * 上传文件方法
161 | *
162 | * @param url url
163 | * @param params 参数
164 | * @param paths 文件路径
165 | * @param callback 回调函数
166 | * @return call
167 | */
168 | public static Call upload(Context context, String url, Map params, List paths, OkCallback callback) {
169 | MultipartBody.Builder builder = new MultipartBody.Builder();
170 | builder.setType(MultipartBody.FORM);
171 | if (params != null && params.size() > 0) {
172 | for (String key : params.keySet()) {
173 | builder.addFormDataPart(key, params.get(key));
174 | }
175 | }
176 | if (paths != null && paths.size() > 0) {
177 | if (paths.size() == 1) {
178 | File file = new File(paths.get(0));
179 | builder.addFormDataPart("file", file.getName(), RequestBody.create(null, file));
180 | } else {
181 | for (int i = 0; i < paths.size(); i++) {
182 | File file = new File(paths.get(i));
183 | builder.addFormDataPart("file[" + i + "]", file.getName(), RequestBody.create(null, file));
184 | }
185 | }
186 | }
187 | RequestBody body = builder.build();
188 | Request request = new Request.Builder().url(url).post(body).build();
189 | Call call = getInstance().newCall(request);
190 | call.enqueue(callback);
191 | return call;
192 | }
193 |
194 |
195 | /**
196 | * 添加参数
197 | *
198 | * @param params 参数值
199 | * @return 参数字符串
200 | */
201 | private static String encodeParameters(Context context, Map params) {
202 | if (params == null) {
203 | params = new HashMap<>();
204 | }
205 | StringBuilder sb = new StringBuilder("");
206 | try {
207 | for (Map.Entry entry : params.entrySet()) {
208 | sb.append(URLEncoder.encode(entry.getKey(),
209 | "UTF-8"));
210 | sb.append('=');
211 | sb.append(URLEncoder.encode(entry.getValue(),
212 | "UTF-8"));
213 | sb.append('&');
214 | }
215 | return sb.toString();
216 | } catch (Exception e) {
217 | }
218 | return sb.toString();
219 | }
220 |
221 | }
222 |
--------------------------------------------------------------------------------
/app/src/main/java/com/smile/taobaodemo/ui/adapter/HomeAdapter.java:
--------------------------------------------------------------------------------
1 | package com.smile.taobaodemo.ui.adapter;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.support.v7.widget.GridLayoutManager;
6 | import android.support.v7.widget.RecyclerView;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.widget.ImageView;
11 | import android.widget.TextView;
12 |
13 | import com.oushangfeng.marqueelayout.MarqueeLayout;
14 | import com.oushangfeng.marqueelayout.MarqueeLayoutAdapter;
15 | import com.smile.taobaodemo.R;
16 | import com.smile.taobaodemo.base.Type;
17 | import com.smile.taobaodemo.model.entity.HomeBase;
18 | import com.smile.taobaodemo.model.entity.HomeTop;
19 | import com.smile.taobaodemo.utils.GlideUtil;
20 | import com.smile.taobaodemo.widget.CirclePageIndicator;
21 | import com.smile.taobaodemo.widget.FooterLoading;
22 |
23 | import java.util.List;
24 | import java.util.Random;
25 |
26 | import butterknife.BindView;
27 | import butterknife.ButterKnife;
28 | import cn.trinea.android.view.autoscrollviewpager.AutoScrollViewPager;
29 |
30 | /**
31 | * @author Smile Wei
32 | * @since 2017/03/01.
33 | */
34 |
35 | public class HomeAdapter extends RecyclerView.Adapter {
36 | private Context context;
37 | private Activity activity;
38 | private List list;
39 | private List loopList;
40 | private List headlineList;
41 | private final SpanSizeLookup spanSizeLookup = new SpanSizeLookup();
42 | private LayoutInflater inflater;
43 |
44 | public HomeAdapter(Context context, Activity activity, List list) {
45 | this.context = context;
46 | this.activity = activity;
47 | this.list = list;
48 | inflater = LayoutInflater.from(context);
49 | }
50 |
51 | public void setLoopList(List loopList) {
52 | this.loopList = loopList;
53 | }
54 |
55 | public void setHeadlineList(List headlineList) {
56 | this.headlineList = headlineList;
57 | }
58 |
59 | public GridLayoutManager.SpanSizeLookup getSpanSizeLookup() {
60 | return spanSizeLookup;
61 | }
62 |
63 | @Override
64 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
65 | View view;
66 | switch (viewType) {
67 | case HomeBase.TYPE_CAROUSEL:
68 | view = inflater.inflate(R.layout.item_home_type_carousel, parent, false);
69 | return new CarouselHolder(view);
70 | case HomeBase.TYPE_CATEGORY:
71 | view = inflater.inflate(R.layout.fragment_navigation_home_category, parent, false);
72 | return new CategoryHolder(view);
73 | case HomeBase.TYPE_HEADLINE:
74 | view = inflater.inflate(R.layout.item_home_type_headline, parent, false);
75 | return new HeadlineHolder(view);
76 | case HomeBase.TYPE_HEADER:
77 | view = inflater.inflate(R.layout.item_home_type_header, parent, false);
78 | return new HeaderHolder(view);
79 | case HomeBase.TYPE_DIVIDER:
80 | view = inflater.inflate(R.layout.item_home_type_divider, parent, false);
81 | return new PlaceHolder(view);
82 | case HomeBase.TYPE_LIVE:
83 | view = inflater.inflate(R.layout.item_home_type_live, parent, false);
84 | return new LiveHolder(view);
85 | case HomeBase.TYPE_HOT:
86 | view = inflater.inflate(R.layout.item_home_type_hot, parent, false);
87 | return new CommonHolder(view);
88 | case HomeBase.TYPE_RECOMMEND:
89 | view = inflater.inflate(R.layout.item_home_type_recommend, parent, false);
90 | return new RecommendHolder(view);
91 | case HomeBase.TYPE_PLACE:
92 | view = inflater.inflate(R.layout.item_place, parent, false);
93 | return new PlaceHolder(view);
94 | default:
95 | view = inflater.inflate(R.layout.item_footer_loading, parent, false);
96 | return new FooterHolder(view);
97 | }
98 | }
99 |
100 | @Override
101 | public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
102 | HomeBase bean = list.get(position);
103 | if (viewHolder instanceof CarouselHolder) {
104 | CarouselHolder holder = (CarouselHolder) viewHolder;
105 | holder.viewPager.setAdapter(new ImageHomeAdapter(context, activity, loopList));
106 | holder.indicator.setViewPager(holder.viewPager);
107 | holder.viewPager.setInterval(4000);
108 | holder.viewPager.setSlideBorderMode(AutoScrollViewPager.SLIDE_BORDER_MODE_TO_PARENT);
109 | holder.viewPager.startAutoScroll();
110 | } else if (viewHolder instanceof HeadlineHolder) {
111 | HeadlineHolder holder = (HeadlineHolder) viewHolder;
112 | MarqueeLayoutAdapter topAdapter = new MarqueeLayoutAdapter(headlineList) {
113 | @Override
114 | protected int getItemLayoutId() {
115 | return R.layout.item_marquee;
116 | }
117 |
118 | @Override
119 | protected void initView(View view, int position, HomeBase item) {
120 | ((TextView) view).setText(item.getName());
121 |
122 | }
123 | };
124 | holder.marqueeLayout.setAdapter(topAdapter);
125 | holder.marqueeLayout.start();
126 | } else if (viewHolder instanceof HeaderHolder) {
127 | HeaderHolder holder = (HeaderHolder) viewHolder;
128 | holder.tvTitle.setText(bean.getName());
129 | } else if (viewHolder instanceof LiveHolder) {
130 | LiveHolder holder = (LiveHolder) viewHolder;
131 | GlideUtil.load(activity, bean.getUrl(), holder.ivHome);
132 | holder.tvTitle.setText(bean.getName());
133 | } else if (viewHolder instanceof CommonHolder) {
134 | CommonHolder holder = (CommonHolder) viewHolder;
135 | GlideUtil.load(activity, bean.getUrl(), holder.ivHome);
136 | holder.tvTitle.setText(bean.getName());
137 | holder.tvPrice.setText(String.format("%s%s", bean.getCurrency(), bean.getPrice()));
138 | } else if (viewHolder instanceof RecommendHolder) {
139 | RecommendHolder holder = (RecommendHolder) viewHolder;
140 | GlideUtil.load(activity, bean.getUrl(), holder.ivHome);
141 | holder.tvTitle.setText(bean.getName());
142 | holder.tvPrice.setText(String.format("%s%s", bean.getCurrency(), bean.getPrice()));
143 | holder.tvCount.setText(String.format("%d人付款", new Random().nextInt(10000)));
144 |
145 | } else if (viewHolder instanceof FooterHolder) {
146 | FooterHolder holder = (FooterHolder) viewHolder;
147 | holder.footerLoading.onLoad(Type.TYPE_FOOTER_FULL == list.get(position).getType());
148 | }
149 | }
150 |
151 | @Override
152 | public int getItemViewType(int position) {
153 | return list.get(position).getType();
154 | }
155 |
156 | @Override
157 | public int getItemCount() {
158 | return list.size();
159 | }
160 |
161 | class CarouselHolder extends RecyclerView.ViewHolder {
162 | @BindView(R.id.view_pager)
163 | AutoScrollViewPager viewPager;
164 | @BindView(R.id.indicator)
165 | CirclePageIndicator indicator;
166 |
167 | CarouselHolder(View itemView) {
168 | super(itemView);
169 | ButterKnife.bind(this, itemView);
170 | }
171 | }
172 |
173 | class HeadlineHolder extends RecyclerView.ViewHolder {
174 | @BindView(R.id.marquee_layout)
175 | MarqueeLayout marqueeLayout;
176 |
177 | HeadlineHolder(View itemView) {
178 | super(itemView);
179 | ButterKnife.bind(this, itemView);
180 | }
181 | }
182 |
183 |
184 | class CommonHolder extends RecyclerView.ViewHolder {
185 | @BindView(R.id.iv_home)
186 | ImageView ivHome;
187 | @BindView(R.id.tv_title)
188 | TextView tvTitle;
189 | @BindView(R.id.tv_price)
190 | TextView tvPrice;
191 |
192 |
193 | CommonHolder(View itemView) {
194 | super(itemView);
195 | ButterKnife.bind(this, itemView);
196 | }
197 |
198 | }
199 |
200 | public interface OnItemClickListener {
201 | void onItemClick(int position);
202 | }
203 |
204 | private OnItemClickListener listener;
205 |
206 | public void setOnItemClickListener(OnItemClickListener listener) {
207 | this.listener = listener;
208 | }
209 |
210 | class RecommendHolder extends RecyclerView.ViewHolder {
211 | @BindView(R.id.iv_home)
212 | ImageView ivHome;
213 | @BindView(R.id.tv_title)
214 | TextView tvTitle;
215 | @BindView(R.id.tv_price)
216 | TextView tvPrice;
217 | @BindView(R.id.tv_count)
218 | TextView tvCount;
219 |
220 | RecommendHolder(View itemView) {
221 | super(itemView);
222 | ButterKnife.bind(this, itemView);
223 |
224 | itemView.setOnClickListener(new View.OnClickListener() {
225 | @Override
226 | public void onClick(View v) {
227 | if (listener != null)
228 | listener.onItemClick(getLayoutPosition());
229 | }
230 | });
231 | }
232 |
233 | }
234 |
235 | class LiveHolder extends RecyclerView.ViewHolder {
236 | @BindView(R.id.iv_home)
237 | ImageView ivHome;
238 | @BindView(R.id.tv_title)
239 | TextView tvTitle;
240 |
241 | LiveHolder(View itemView) {
242 | super(itemView);
243 | ButterKnife.bind(this, itemView);
244 | }
245 |
246 | }
247 |
248 | class HeaderHolder extends RecyclerView.ViewHolder {
249 | @BindView(R.id.tv_title)
250 | TextView tvTitle;
251 |
252 | HeaderHolder(View itemView) {
253 | super(itemView);
254 | ButterKnife.bind(this, itemView);
255 | }
256 | }
257 |
258 | private class PlaceHolder extends RecyclerView.ViewHolder {
259 | PlaceHolder(View itemView) {
260 | super(itemView);
261 | }
262 | }
263 |
264 |
265 | private class SpanSizeLookup extends GridLayoutManager.SpanSizeLookup {
266 | @Override
267 | public int getSpanSize(int position) {
268 | return list.get(position).getSpanCount();
269 | }
270 | }
271 |
272 | class CategoryHolder extends RecyclerView.ViewHolder {
273 |
274 | CategoryHolder(View view) {
275 | super(view);
276 | ButterKnife.bind(this, view);
277 | }
278 | }
279 |
280 | class FooterHolder extends RecyclerView.ViewHolder {
281 | @BindView(R.id.footer)
282 | FooterLoading footerLoading;
283 |
284 | FooterHolder(View itemView) {
285 | super(itemView);
286 | ButterKnife.bind(this, itemView);
287 | }
288 | }
289 | }
290 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_goods_detail_top.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
17 |
18 |
22 |
23 |
30 |
31 |
32 |
33 |
42 |
43 |
53 |
54 |
55 |
62 |
63 |
64 |
69 |
70 |
77 |
78 |
79 |
80 |
84 |
85 |
90 |
91 |
97 |
98 |
106 |
107 |
115 |
116 |
124 |
125 |
132 |
133 |
139 |
140 |
141 |
142 |
146 |
147 |
154 |
155 |
163 |
164 |
172 |
173 |
174 |
175 |
182 |
183 |
191 |
192 |
200 |
201 |
202 |
203 |
210 |
211 |
219 |
220 |
227 |
228 |
229 |
230 |
235 |
236 |
245 |
246 |
247 |
251 |
252 |
260 |
261 |
269 |
270 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
--------------------------------------------------------------------------------