From 3978ab95f4261fd69ddbf952a1e7f78abe540dc7 Mon Sep 17 00:00:00 2001 From: kehaoyuan Date: Mon, 4 Dec 2017 18:47:53 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E9=80=9A=E7=94=A8=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E6=A8=A1=E5=9D=97=EF=BC=8C=E9=97=AE=E7=AD=94=E7=B2=BE?= =?UTF-8?q?=E9=80=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/gh/common/constant/ItemViewType.java | 8 + .../common/view/VerticalItemDecoration.java | 8 +- .../adapter/viewholder/FooterViewHolder.java | 26 ++ .../com/gh/gamecenter/ask/AskFragment.java | 93 +++++++ .../com/gh/gamecenter/ask/AskHotAdapter.java | 98 +++++++ .../com/gh/gamecenter/ask/AskHotFragment.java | 48 ++++ .../gh/gamecenter/ask/AskItemViewHolder.java | 37 +++ .../gamecenter/ask/AskQuestionsFragment.java | 15 + .../gamecenter/baselist/BaseListAdapter.java | 12 +- .../gamecenter/baselist/BaseListContrat.java | 68 ----- .../gamecenter/baselist/BaseListFragment.java | 53 ---- .../baselist/BaseListPresenterImpl.java | 206 -------------- .../gh/gamecenter/baselist/ListFragment.java | 144 ++++++++++ .../gamecenter/baselist/ListRepository.java | 123 +++++++++ .../gh/gamecenter/baselist/ListViewModel.java | 61 +++++ .../gh/gamecenter/baselist/LoadStatus.java | 22 ++ .../com/gh/gamecenter/baselist/LoadType.java | 20 ++ .../baselist/OnListLoadListener.java | 29 ++ .../gh/gamecenter/baselist/TestAdapter.java | 259 ------------------ .../gh/gamecenter/baselist/TestFragment.java | 86 ------ .../gh/gamecenter/fragment/MainFragment.java | 7 +- .../res/drawable-xxhdpi/ic_ask_search.png | Bin 0 -> 1125 bytes .../res/drawable-xxhdpi/ic_ask_select.png | Bin 0 -> 3014 bytes .../res/drawable-xxhdpi/ic_ask_selectgame.png | Bin 0 -> 518 bytes .../res/drawable-xxhdpi/ic_ask_unselect.png | Bin 0 -> 2985 bytes app/src/main/res/drawable/selector_ic_ask.xml | 8 + app/src/main/res/layout/ask_item.xml | 70 +++++ app/src/main/res/layout/fragment_ask.xml | 80 ++++++ app/src/main/res/layout/fragment_main.xml | 26 ++ app/src/main/res/values/colors.xml | 26 +- app/src/main/res/values/strings.xml | 3 + 31 files changed, 944 insertions(+), 692 deletions(-) create mode 100644 app/src/main/java/com/gh/gamecenter/ask/AskFragment.java create mode 100644 app/src/main/java/com/gh/gamecenter/ask/AskHotAdapter.java create mode 100644 app/src/main/java/com/gh/gamecenter/ask/AskHotFragment.java create mode 100644 app/src/main/java/com/gh/gamecenter/ask/AskItemViewHolder.java create mode 100644 app/src/main/java/com/gh/gamecenter/ask/AskQuestionsFragment.java delete mode 100644 app/src/main/java/com/gh/gamecenter/baselist/BaseListContrat.java delete mode 100644 app/src/main/java/com/gh/gamecenter/baselist/BaseListFragment.java delete mode 100644 app/src/main/java/com/gh/gamecenter/baselist/BaseListPresenterImpl.java create mode 100644 app/src/main/java/com/gh/gamecenter/baselist/ListFragment.java create mode 100644 app/src/main/java/com/gh/gamecenter/baselist/ListRepository.java create mode 100644 app/src/main/java/com/gh/gamecenter/baselist/ListViewModel.java create mode 100644 app/src/main/java/com/gh/gamecenter/baselist/LoadStatus.java create mode 100644 app/src/main/java/com/gh/gamecenter/baselist/LoadType.java create mode 100644 app/src/main/java/com/gh/gamecenter/baselist/OnListLoadListener.java delete mode 100644 app/src/main/java/com/gh/gamecenter/baselist/TestAdapter.java delete mode 100644 app/src/main/java/com/gh/gamecenter/baselist/TestFragment.java create mode 100644 app/src/main/res/drawable-xxhdpi/ic_ask_search.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_ask_select.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_ask_selectgame.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_ask_unselect.png create mode 100644 app/src/main/res/drawable/selector_ic_ask.xml create mode 100644 app/src/main/res/layout/ask_item.xml create mode 100644 app/src/main/res/layout/fragment_ask.xml diff --git a/app/src/main/java/com/gh/common/constant/ItemViewType.java b/app/src/main/java/com/gh/common/constant/ItemViewType.java index 7d28789e60..7117d0d930 100644 --- a/app/src/main/java/com/gh/common/constant/ItemViewType.java +++ b/app/src/main/java/com/gh/common/constant/ItemViewType.java @@ -24,4 +24,12 @@ public class ItemViewType { public static final int KC_HINT = 17; public static final int GAME_PULGIN = 18; // 游戏插件模块 + /** + * 普通列表 + */ + public static final int ITEM_BODY = 100; + public static final int ITEM_FOOTER = 101; + public static final int ITEM_TOP = 102; + + } diff --git a/app/src/main/java/com/gh/common/view/VerticalItemDecoration.java b/app/src/main/java/com/gh/common/view/VerticalItemDecoration.java index 9980323a2a..c1e1f05cdc 100644 --- a/app/src/main/java/com/gh/common/view/VerticalItemDecoration.java +++ b/app/src/main/java/com/gh/common/view/VerticalItemDecoration.java @@ -15,13 +15,13 @@ public class VerticalItemDecoration extends RecyclerView.ItemDecoration { private Paint paint; private int mInterval = 0; - private boolean isShowIntervalTop; + private boolean mIsShowIntervalTop; public VerticalItemDecoration(Context context, int interval, boolean isShowIntervalTop) { paint = new Paint(); paint.setColor(ContextCompat.getColor(context, R.color.background)); mInterval = DisplayUtils.dip2px(context, interval); - this.isShowIntervalTop = isShowIntervalTop; + mIsShowIntervalTop = isShowIntervalTop; } @Override @@ -35,7 +35,7 @@ public class VerticalItemDecoration extends RecyclerView.ItemDecoration { int top = child.getBottom() + layoutParams.bottomMargin; int bottom = top + mInterval; - if (i == 0 && isShowIntervalTop) { + if (i == 0 && mIsShowIntervalTop) { c.drawRect(left, 0, right, bottom, paint); } else { c.drawRect(left, top, right, bottom, paint); @@ -47,7 +47,7 @@ public class VerticalItemDecoration extends RecyclerView.ItemDecoration { public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { int position = parent.getChildPosition(view); - if (position == 0 && isShowIntervalTop) { + if (position == 0 && mIsShowIntervalTop) { outRect.set(0, mInterval, 0, mInterval); } else { outRect.set(0, 0, 0, mInterval); diff --git a/app/src/main/java/com/gh/gamecenter/adapter/viewholder/FooterViewHolder.java b/app/src/main/java/com/gh/gamecenter/adapter/viewholder/FooterViewHolder.java index bd10106f8e..4ac0836700 100644 --- a/app/src/main/java/com/gh/gamecenter/adapter/viewholder/FooterViewHolder.java +++ b/app/src/main/java/com/gh/gamecenter/adapter/viewholder/FooterViewHolder.java @@ -6,6 +6,7 @@ import android.widget.ProgressBar; import android.widget.TextView; import com.gh.base.BaseRecyclerViewHolder; +import com.gh.base.OnListClickListener; import com.gh.gamecenter.R; import butterknife.BindView; @@ -35,11 +36,36 @@ public class FooterViewHolder extends BaseRecyclerViewHolder { super(itemView); } + public FooterViewHolder(View itemView, Object data, OnListClickListener listClickListener) { + super(itemView, data, listClickListener); + itemView.setOnClickListener(this); + } + // 减去recyclerView item间隔(个别列表间隔很大) public void initItemPadding() { itemView.setPadding(0, 0, 0, 0); } + public void initFooterViewHolder(boolean isNetworkError, boolean isOver) { + if (isNetworkError) { + lineLeft.setVisibility(View.GONE); + lineRight.setVisibility(View.GONE); + loading.setVisibility(View.GONE); + hint.setText(R.string.loading_failed_retry); + } else if (isOver) { + lineLeft.setVisibility(View.VISIBLE); + lineRight.setVisibility(View.VISIBLE); + loading.setVisibility(View.GONE); + hint.setText(R.string.loading_complete); + } else { + lineLeft.setVisibility(View.GONE); + lineRight.setVisibility(View.GONE); + loading.setVisibility(View.VISIBLE); + hint.setText(R.string.loading); + } + } + + public void initFooterViewHolder(boolean mIsNetworkError, boolean mIsOver, OnClickListener onClickListener) { if (mIsNetworkError) { lineLeft.setVisibility(View.GONE); diff --git a/app/src/main/java/com/gh/gamecenter/ask/AskFragment.java b/app/src/main/java/com/gh/gamecenter/ask/AskFragment.java new file mode 100644 index 0000000000..9b3671242a --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/ask/AskFragment.java @@ -0,0 +1,93 @@ +package com.gh.gamecenter.ask; + +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.view.View; +import android.widget.CheckedTextView; +import android.widget.ImageView; +import android.widget.TextView; + +import com.gh.base.adapter.FragmentAdapter; +import com.gh.base.fragment.BaseFragment; +import com.gh.gamecenter.R; +import com.lightgame.view.NoScrollableViewPager; + +import java.util.ArrayList; + +import butterknife.BindView; +import butterknife.OnClick; + +/** + * Created by khy on 2/12/17. + */ + +public class AskFragment extends BaseFragment { + + @BindView(R.id.ask_selectgame) + ImageView mAskSelectgame; + @BindView(R.id.ask_gamename) + TextView mAskGamename; + @BindView(R.id.ask_search) + ImageView mAskSearch; + @BindView(R.id.ask_hot) + CheckedTextView mAskHot; + @BindView(R.id.ask_questions) + CheckedTextView mAskQuestions; + @BindView(R.id.ask_viewpager) + NoScrollableViewPager mAskViewpager; + + public static final int INDEX_HOT = 0; + public static final int INDEX_QUESTIONS = 1; + + @Override + protected int getLayoutId() { + return R.layout.fragment_ask; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + initViewPager(); + setTabbarPosition(INDEX_HOT); + } + + @OnClick({R.id.ask_selectgame, R.id.ask_search, R.id.ask_hot, R.id.ask_questions}) + public void onViewClicked(View view) { + switch (view.getId()) { + case R.id.ask_selectgame: + break; + case R.id.ask_search: + break; + case R.id.ask_hot: + setTabbarPosition(INDEX_HOT); + break; + case R.id.ask_questions: + setTabbarPosition(INDEX_QUESTIONS); + break; + } + } + + private void initViewPager() { + ArrayList fragmentList = new ArrayList<>(); + fragmentList.add(new AskHotFragment()); + fragmentList.add(new AskQuestionsFragment()); + mAskViewpager.setAdapter(new FragmentAdapter(getChildFragmentManager(), fragmentList)); + mAskViewpager.setScrollable(false); + } + + private void setTabbarPosition(int index) { + switch (index) { + case INDEX_HOT: + mAskHot.setChecked(true); + mAskQuestions.setChecked(false); + break; + case INDEX_QUESTIONS: + mAskHot.setChecked(false); + mAskQuestions.setChecked(true); + break; + } + mAskViewpager.setCurrentItem(index); + } +} diff --git a/app/src/main/java/com/gh/gamecenter/ask/AskHotAdapter.java b/app/src/main/java/com/gh/gamecenter/ask/AskHotAdapter.java new file mode 100644 index 0000000000..feabf2c96c --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/ask/AskHotAdapter.java @@ -0,0 +1,98 @@ +package com.gh.gamecenter.ask; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.view.ViewGroup; + +import com.gh.base.OnListClickListener; +import com.gh.common.constant.ItemViewType; +import com.gh.gamecenter.R; +import com.gh.gamecenter.adapter.viewholder.FooterViewHolder; +import com.gh.gamecenter.baselist.BaseListAdapter; +import com.gh.gamecenter.baselist.LoadStatus; +import com.gh.gamecenter.entity.NewsEntity; + +import java.util.List; + +/** + * Created by khy on 2/12/17. + */ + +public class AskHotAdapter extends BaseListAdapter { + + private OnListClickListener mListClickListener; + + private List mEntityList; + + public AskHotAdapter(Context context, OnListClickListener listClickListener) { + super(context); + mListClickListener = listClickListener; + } + + @NonNull + @Override + protected void provideListData(List listData) { + mEntityList = (List) listData; + notifyDataSetChanged(); + } + + @Override + protected void loadChange(LoadStatus status) { + switch (status) { + case over: + mIsOver = true; + break; + case error: + mIsNetworkError = true; + break; + case retry: + mIsNetworkError = false; + break; + } + notifyItemChanged(getItemCount() - 1); + } + + @Override + public int getItemViewType(int position) { + if (position == getItemCount() - 1) return ItemViewType.ITEM_FOOTER; + return ItemViewType.ITEM_BODY; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view; + switch (viewType) { + case ItemViewType.ITEM_FOOTER: + view = mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false); + return new FooterViewHolder(view, null, mListClickListener); + case ItemViewType.ITEM_BODY: + view = mLayoutInflater.inflate(R.layout.ask_item, parent, false); + return new AskItemViewHolder(view, mEntityList, mListClickListener); + default: + return null; + } + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + switch (getItemViewType(position)) { + case ItemViewType.ITEM_BODY: + NewsEntity newsEntity = mEntityList.get(position); + AskItemViewHolder askHolder = (AskItemViewHolder) holder; + askHolder.mAskUsername.setText(newsEntity.getTitle()); + break; + case ItemViewType.ITEM_FOOTER: + FooterViewHolder footerViewHolder = (FooterViewHolder) holder; + footerViewHolder.initItemPadding(); + footerViewHolder.initFooterViewHolder(mIsNetworkError, mIsOver); + break; + } + } + + @Override + public int getItemCount() { + return mEntityList == null || mEntityList.isEmpty() ? 0 : mEntityList.size() + FOOTER_ITEM_COUNT; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/ask/AskHotFragment.java b/app/src/main/java/com/gh/gamecenter/ask/AskHotFragment.java new file mode 100644 index 0000000000..b804e685de --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/ask/AskHotFragment.java @@ -0,0 +1,48 @@ +package com.gh.gamecenter.ask; + +import android.view.View; + +import com.gh.gamecenter.R; +import com.gh.gamecenter.baselist.BaseListAdapter; +import com.gh.gamecenter.baselist.ListFragment; +import com.gh.gamecenter.baselist.LoadStatus; +import com.gh.gamecenter.baselist.LoadType; +import com.gh.gamecenter.entity.NewsEntity; +import com.gh.gamecenter.retrofit.RetrofitManager; + +import java.util.List; + +import rx.Observable; + +/** + * Created by khy on 2/12/17. + */ + +public class AskHotFragment extends ListFragment { + + private AskHotAdapter mAdapter; + + @SuppressWarnings("unchecked") + @Override + public Observable> provideDataObservable() { + return RetrofitManager.getInstance(getContext()).getApi().getZiXun(getListOffset()); + } + + @Override + protected BaseListAdapter provideListAdapter() { + return mAdapter == null ? mAdapter = new AskHotAdapter(getContext(), this) : mAdapter; + } + + @Override + public void onListClick(View view, int position, Object data) { + switch (view.getId()) { + case R.id.footerview_item: + if (mAdapter.isNetworkError()) { + mAdapter.loadChange(LoadStatus.retry); + mListViewModel.load(LoadType.retry); + } + break; + } + + } +} diff --git a/app/src/main/java/com/gh/gamecenter/ask/AskItemViewHolder.java b/app/src/main/java/com/gh/gamecenter/ask/AskItemViewHolder.java new file mode 100644 index 0000000000..a87ca99370 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/ask/AskItemViewHolder.java @@ -0,0 +1,37 @@ +package com.gh.gamecenter.ask; + +import android.view.View; +import android.widget.TextView; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.gh.base.BaseRecyclerViewHolder; +import com.gh.base.OnListClickListener; +import com.gh.gamecenter.R; + +import butterknife.BindView; + +/** + * Created by khy on 4/12/17. + */ + +public class AskItemViewHolder extends BaseRecyclerViewHolder { + + + @BindView(R.id.ask_item_usericon) + SimpleDraweeView mAskUsericon; + @BindView(R.id.ask_item_username) + TextView mAskUsername; + @BindView(R.id.ask_item_title) + TextView mAskTitle; + @BindView(R.id.ask_item_content) + TextView mAskContent; + @BindView(R.id.ask_item_img) + SimpleDraweeView mAskImg; + @BindView(R.id.ask_item_votecount) + TextView mAskVotecount; + + public AskItemViewHolder(View itemView, Object data, OnListClickListener listClickListener) { + super(itemView, data, listClickListener); + itemView.setOnClickListener(this); + } +} diff --git a/app/src/main/java/com/gh/gamecenter/ask/AskQuestionsFragment.java b/app/src/main/java/com/gh/gamecenter/ask/AskQuestionsFragment.java new file mode 100644 index 0000000000..4d18f6f3f8 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/ask/AskQuestionsFragment.java @@ -0,0 +1,15 @@ +package com.gh.gamecenter.ask; + +import com.gh.base.fragment.BaseFragment; +import com.gh.gamecenter.R; + +/** + * Created by khy on 2/12/17. + */ + +public class AskQuestionsFragment extends BaseFragment { + @Override + protected int getLayoutId() { + return R.layout.game_normal_item; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/baselist/BaseListAdapter.java b/app/src/main/java/com/gh/gamecenter/baselist/BaseListAdapter.java index f4a57cc68f..b7d495daf4 100644 --- a/app/src/main/java/com/gh/gamecenter/baselist/BaseListAdapter.java +++ b/app/src/main/java/com/gh/gamecenter/baselist/BaseListAdapter.java @@ -12,13 +12,21 @@ import java.util.List; public abstract class BaseListAdapter extends BaseRecyclerAdapter { + protected static final int FOOTER_ITEM_COUNT = 1; + + protected boolean mIsOver; + + protected boolean mIsNetworkError; + public BaseListAdapter(Context context) { super(context); } protected abstract void provideListData(List listData); - protected abstract void loadError(Throwable e); + protected abstract void loadChange(LoadStatus status); - protected abstract void refreshData(); + public boolean isNetworkError() { + return mIsNetworkError; + } } diff --git a/app/src/main/java/com/gh/gamecenter/baselist/BaseListContrat.java b/app/src/main/java/com/gh/gamecenter/baselist/BaseListContrat.java deleted file mode 100644 index b067a4ab15..0000000000 --- a/app/src/main/java/com/gh/gamecenter/baselist/BaseListContrat.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.gh.gamecenter.baselist; - -import android.view.View; - -import java.util.List; - -import rx.Observable; - -/** - * Created by khy on 6/11/17. - */ -class BaseListContrat { - - interface ListAppView { - - /** - * 加载完成(不是结束) - * - * @param dataList 当前加载数据(不是全部) - * @param - */ - void LoadFinish(List dataList); - - /** - * 加载失败,注意首次加载和分页加载 - * - * @param e - */ - void LoadError(Throwable e); - - /** - * 提供数据源头 - * - * @param - * @return - */ - Observable> provideDataObservable(); - - /** - * 列表 RecyclerView Adapter - * - * @return - */ - BaseListAdapter provideRecyclerAdapter(); - - } - - interface BaseListPresenter { - - /** - * 加载数据, 无论是初始化还是分页都只用一个(注意控制 ListSize-offset) - */ - void load(); - - /** - * 加载重试 - */ - void retryLoad(); - - /** - * 提供 Fragment View 可以不传, 不传的话自己搞 - * - * @param view Fragment View - */ - void provideView(View view); - - } -} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/baselist/BaseListFragment.java b/app/src/main/java/com/gh/gamecenter/baselist/BaseListFragment.java deleted file mode 100644 index 749bf949e3..0000000000 --- a/app/src/main/java/com/gh/gamecenter/baselist/BaseListFragment.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.gh.gamecenter.baselist; - -import android.os.Bundle; -import android.support.annotation.Nullable; -import android.view.View; - -import com.gh.base.fragment.BaseFragment; -import com.gh.gamecenter.R; - -import java.util.List; - -/** - * Created by khy on 11/11/17. - */ - -public abstract class BaseListFragment extends BaseFragment implements BaseListContrat.ListAppView { - - protected BaseListPresenterImpl mListPresenter; - - @Override - protected int getLayoutId() { - return R.layout.fragment_list_base; - } - - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - mListPresenter = new BaseListPresenterImpl(this, getContext()); - } - - @Override - public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - mListPresenter.provideView(view); - } - - protected abstract BaseListAdapter provideAdapter(); - - @Override - public void LoadFinish(List dataList) { - provideAdapter().provideListData(dataList); - } - - @Override - public void LoadError(Throwable e) { - provideAdapter().loadError(e); - } - - @Override - public BaseListAdapter provideRecyclerAdapter() { - return provideAdapter(); - } -} diff --git a/app/src/main/java/com/gh/gamecenter/baselist/BaseListPresenterImpl.java b/app/src/main/java/com/gh/gamecenter/baselist/BaseListPresenterImpl.java deleted file mode 100644 index f7f91fbb5b..0000000000 --- a/app/src/main/java/com/gh/gamecenter/baselist/BaseListPresenterImpl.java +++ /dev/null @@ -1,206 +0,0 @@ -package com.gh.gamecenter.baselist; - -import android.content.Context; -import android.support.v4.widget.SwipeRefreshLayout; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.view.View; - -import com.gh.gamecenter.R; -import com.gh.gamecenter.retrofit.Response; -import com.lightgame.utils.Utils; - -import java.util.List; - -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; - -/** - * Created by khy on 6/11/17. - */ - -public class BaseListPresenterImpl implements BaseListContrat.BaseListPresenter { - - public final static int PAGE_SIZE = 20; - - private final static String TAG = "BaseListPresenterImpl"; - - private Context mContext; - - private BaseListContrat.ListAppView mListAppView; - - private RecyclerView mListRv; - private SwipeRefreshLayout mRefreshLayout; - private View mLoadingView; - private View mNoConnView; - private View mNoDataView; - - private LinearLayoutManager mLayoutManager; - - private int mListSize; // 相当于load offset - - private boolean mIsLoading; - private boolean mIsNetworkError; - private boolean mIsOver; - - public BaseListPresenterImpl(BaseListContrat.ListAppView listAppView, Context context) { - this.mListAppView = listAppView; - this.mContext = context; - this.mListSize = 0; - } - - @Override - public void provideView(View view) { - if (view == null) { - Utils.log(TAG, "provideView View 为空, Fragment自己处理"); - return; - } - - if (mListAppView.provideRecyclerAdapter() == null) { - throw new NullPointerException("recycler is null - 请注意初始化先后顺序"); - } - - mLayoutManager = new LinearLayoutManager(mContext); - - mLoadingView = view.findViewById(R.id.list_loading); - mNoConnView = view.findViewById(R.id.reuse_no_connection); - mNoDataView = view.findViewById(R.id.reuse_none_data); - mRefreshLayout = view.findViewById(R.id.list_refresh); - mRefreshLayout.setColorSchemeResources(R.color.theme); - mListRv = view.findViewById(R.id.list_rv); - mListRv.setLayoutManager(mLayoutManager); - mListRv.setAdapter(mListAppView.provideRecyclerAdapter()); - - mListRv.addOnScrollListener(new RecyclerView.OnScrollListener() { - @Override - public void onScrollStateChanged(RecyclerView recyclerView, int newState) { - super.onScrollStateChanged(recyclerView, newState); - if (newState == RecyclerView.SCROLL_STATE_IDLE - && mLayoutManager.findLastVisibleItemPosition() + 1 == mLayoutManager.getItemCount()) { - if (!mIsOver && !mIsNetworkError && !mIsLoading) { - load(); - } - } - } - }); - - mRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { - @Override - public void onRefresh() { - initListStatus(); - mListAppView.provideRecyclerAdapter().refreshData(); - load(); - } - }); - - mNoConnView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - initListStatus(); - initLoadView(true, false, -1, -1); - load(); - } - }); - } - - @Override - public void load() { - if (mListAppView.provideDataObservable() == null) { - throw new NullPointerException("List data Observable is null"); - } - - mIsLoading = true; - - mListAppView - .provideDataObservable() - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Response>() { - @Override - public void onNext(List response) { - super.onNext(response); - int size = response.size(); - - mListAppView.LoadFinish(response); - - initLoadView(false, false, mListSize, size); - - if (size < PAGE_SIZE) { - mIsOver = true; - } - - mIsLoading = false; - mIsNetworkError = false; - - mListSize += size; - } - - @Override - public void onError(Throwable e) { - super.onError(e); - - mIsLoading = false; - mIsNetworkError = true; - - mListAppView.LoadError(e); - - initLoadView(false, true, mListSize, -1); - } - }); - } - - @Override - public void retryLoad() { - mIsLoading = false; - mIsOver = false; - mIsNetworkError = false; - load(); - } - - - public int getListOffset() { - return mListSize; - } - - - private void initListStatus() { - mIsLoading = false; - mIsOver = false; - mIsNetworkError = false; - mListSize = 0; - } - - private void initLoadView(boolean isRefresh, boolean isLoadError, int offset, int curListSize) { - if (mLoadingView != null && mNoConnView != null && mNoDataView != null) { - - if (isRefresh) { // 下拉刷新 - mLoadingView.setVisibility(View.VISIBLE); - mNoDataView.setVisibility(View.GONE); - mNoConnView.setVisibility(View.GONE); - mListRv.setVisibility(View.GONE); - mRefreshLayout.setRefreshing(false); - - } else if (isLoadError && offset == 0) { // 加载失败(第一页) - mLoadingView.setVisibility(View.GONE); - mNoDataView.setVisibility(View.GONE); - mNoConnView.setVisibility(View.VISIBLE); - mListRv.setVisibility(View.GONE); - mRefreshLayout.setRefreshing(false); - - } else if (offset == 0 && curListSize == 0) { // 数据数据为空 - mLoadingView.setVisibility(View.GONE); - mNoDataView.setVisibility(View.VISIBLE); - mNoConnView.setVisibility(View.GONE); - mListRv.setVisibility(View.GONE); - mRefreshLayout.setRefreshing(false); - - } else { // 正常加载 - mLoadingView.setVisibility(View.GONE); - mNoDataView.setVisibility(View.GONE); - mNoConnView.setVisibility(View.GONE); - mListRv.setVisibility(View.VISIBLE); - mRefreshLayout.setRefreshing(false); - } - } - } -} diff --git a/app/src/main/java/com/gh/gamecenter/baselist/ListFragment.java b/app/src/main/java/com/gh/gamecenter/baselist/ListFragment.java new file mode 100644 index 0000000000..a07c947fce --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/baselist/ListFragment.java @@ -0,0 +1,144 @@ +package com.gh.gamecenter.baselist; + +import android.arch.lifecycle.Observer; +import android.arch.lifecycle.ViewModelProviders; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.widget.LinearLayout; + +import com.gc.materialdesign.views.ProgressBarCircularIndeterminate; +import com.gh.base.fragment.BaseFragment; +import com.gh.common.view.VerticalItemDecoration; +import com.gh.gamecenter.R; + +import java.util.List; + +import butterknife.BindView; +import butterknife.OnClick; + +/** + * Created by khy on 2/12/17. + */ + +public abstract class ListFragment extends BaseFragment implements + Observer>, + OnListLoadListener, + SwipeRefreshLayout.OnRefreshListener { + + @BindView(R.id.list_rv) + RecyclerView mListRv; + @BindView(R.id.list_refresh) + SwipeRefreshLayout mListRefresh; + @BindView(R.id.list_loading) + ProgressBarCircularIndeterminate mListLoading; + @BindView(R.id.reuse_no_connection) + LinearLayout mReuseNoConn; + @BindView(R.id.reuse_none_data) + LinearLayout mReuseNoData; + + private LinearLayoutManager mLayoutManager; + + protected ListViewModel mListViewModel; + + protected abstract BaseListAdapter provideListAdapter(); + + + @Override + protected int getLayoutId() { + return R.layout.fragment_list_base; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + final ListViewModel.Factory factory = new ListViewModel.Factory(getActivity().getApplication(), this); + mListViewModel = ViewModelProviders.of(this, factory).get(ListViewModel.class); + mListViewModel.getObsListData().observe(this, this); + mListViewModel.load(LoadType.nomarl); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + mListRefresh.setOnRefreshListener(this); + mLayoutManager = new LinearLayoutManager(getContext()); + mListRv.setLayoutManager(mLayoutManager); + mListRv.setAdapter(provideListAdapter()); + mListRv.addItemDecoration(new VerticalItemDecoration(getContext(), 8, true)); + mListRv.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + if (mLayoutManager.findLastVisibleItemPosition() == provideListAdapter().getItemCount() - 1 && + RecyclerView.SCROLL_STATE_IDLE == newState) + mListViewModel.load(LoadType.nomarl); + } + }); + } + + protected int getListOffset() { + return mListViewModel == null ? 0 : mListViewModel.getListOffset(); + } + + @Override + public void onRefresh() { + mListViewModel.load(LoadType.refresh); + } + + @Override + public void onChanged(@Nullable List ts) { + provideListAdapter().provideListData(ts); + } + + @OnClick(R.id.reuse_no_connection) + public void onClick(View view) { + mReuseNoConn.setVisibility(View.GONE); + mReuseNoData.setVisibility(View.GONE); + mListLoading.setVisibility(View.VISIBLE); + mListRv.setVisibility(View.GONE); + mListRefresh.setRefreshing(false); + + mListViewModel.load(LoadType.refresh); + } + + @Override + public void onLoadDone() { + mReuseNoConn.setVisibility(View.GONE); + mReuseNoData.setVisibility(View.GONE); + mListLoading.setVisibility(View.GONE); + mListRv.setVisibility(View.VISIBLE); + mListRefresh.setRefreshing(false); + } + + @Override + public void onLoadError() { + mReuseNoConn.setVisibility(View.VISIBLE); + mReuseNoData.setVisibility(View.GONE); + mListLoading.setVisibility(View.GONE); + mListRv.setVisibility(View.GONE); + mListRefresh.setRefreshing(false); + } + + @Override + public void onLoadEmpty() { + mReuseNoConn.setVisibility(View.GONE); + mReuseNoData.setVisibility(View.VISIBLE); + mListLoading.setVisibility(View.GONE); + mListRv.setVisibility(View.GONE); + mListRefresh.setRefreshing(false); + } + + @Override + public void onLoadMoreError() { + provideListAdapter().loadChange(LoadStatus.error); + } + + @Override + public void onLoadOver() { + provideListAdapter().loadChange(LoadStatus.over); + } +} diff --git a/app/src/main/java/com/gh/gamecenter/baselist/ListRepository.java b/app/src/main/java/com/gh/gamecenter/baselist/ListRepository.java new file mode 100644 index 0000000000..4ae36d9287 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/baselist/ListRepository.java @@ -0,0 +1,123 @@ +package com.gh.gamecenter.baselist; + +import android.arch.lifecycle.LiveData; +import android.arch.lifecycle.MutableLiveData; + +import com.gh.gamecenter.retrofit.Response; + +import java.util.ArrayList; +import java.util.List; + +import retrofit2.HttpException; +import rx.Observable; +import rx.android.schedulers.AndroidSchedulers; +import rx.schedulers.Schedulers; + +/** + * Created by khy on 2/12/17. + */ + +public class ListRepository { + + public final static int PAGE_SIZE = 20; + + private MutableLiveData> mListLiveData; + private List mCacheListData; + + private OnListLoadListener mLoadListener; + + private boolean mIsLoading; + private boolean mIsOver; + private boolean mIsNetworkError; + + private int mListOffset; + + + public ListRepository(OnListLoadListener loadListener) { + mListOffset = 0; + mLoadListener = loadListener; + mCacheListData = new ArrayList<>(); + mListLiveData = new MutableLiveData<>(); + } + + private void loadData() { + Observable> listObservable = mLoadListener.provideDataObservable(); + + if (mIsLoading || mIsOver || mIsNetworkError || listObservable == null) return; + + mIsLoading = true; + + listObservable + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Response>() { + @Override + public void onResponse(List response) { + super.onResponse(response); + int size = response.size(); + if (size == 0) { + mLoadListener.onLoadEmpty(); + } else { + if (size < PAGE_SIZE) { + mIsOver = true; + mLoadListener.onLoadOver(); + } + mIsLoading = false; + mIsNetworkError = false; + mListOffset += size; + mLoadListener.onLoadDone(); + cacheAndNotifyListData(response); + } + } + + @Override + public void onFailure(HttpException e) { + super.onFailure(e); + mIsLoading = false; + mIsNetworkError = true; + if (mListOffset > 0) { + mLoadListener.onLoadMoreError(); + } else { + mLoadListener.onLoadError(); + } + } + }); + } + + private void resetOffset() { + mListOffset = 0; + mIsOver = false; + mIsNetworkError = false; + mCacheListData.clear(); + } + + protected void load(LoadType loadType) { + if (loadType == null) loadType = LoadType.nomarl; + switch (loadType) { + case refresh: + resetOffset(); + break; + case retry: + mIsNetworkError = false; + break; + } + loadData(); + } + + protected int getListOffset() { + return mListOffset; + } + + + private void cacheAndNotifyListData(List listData) { + mCacheListData.addAll(listData); + mListLiveData.postValue(mCacheListData); + } + + public LiveData> getListLiveData() { + if (mCacheListData != null) { + mListLiveData.postValue(mCacheListData); + } + return mListLiveData; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/baselist/ListViewModel.java b/app/src/main/java/com/gh/gamecenter/baselist/ListViewModel.java new file mode 100644 index 0000000000..8c8ca34b5e --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/baselist/ListViewModel.java @@ -0,0 +1,61 @@ +package com.gh.gamecenter.baselist; + +import android.app.Application; +import android.arch.lifecycle.AndroidViewModel; +import android.arch.lifecycle.LiveData; +import android.arch.lifecycle.ViewModel; +import android.arch.lifecycle.ViewModelProvider; +import android.support.annotation.NonNull; + +import java.util.List; + +/** + * Created by khy on 2/12/17. + */ + +public class ListViewModel extends AndroidViewModel { + + private ListRepository mRepository; + + private LiveData> mLiveListData; + + + public ListViewModel(Application application, ListRepository repository) { + super(application); + mRepository = repository; + mLiveListData = mRepository.getListLiveData(); + + } + + public LiveData> getObsListData() { + return mLiveListData; + } + + + public void load(LoadType loadType) { + mRepository.load(loadType); + } + + public int getListOffset() { + return mRepository.getListOffset(); + } + + public static class Factory extends ViewModelProvider.NewInstanceFactory { + @NonNull + private final Application mApplication; + + private final ListRepository mRepository; + + public Factory(@NonNull Application application, OnListLoadListener loadListener) { + mApplication = application; + mRepository = new ListRepository(loadListener); + } + + @Override + public T create(Class modelClass) { + //noinspection unchecked + return (T) new ListViewModel(mApplication, mRepository); + } + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/baselist/LoadStatus.java b/app/src/main/java/com/gh/gamecenter/baselist/LoadStatus.java new file mode 100644 index 0000000000..67205ce07c --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/baselist/LoadStatus.java @@ -0,0 +1,22 @@ +package com.gh.gamecenter.baselist; + +/** + * Created by khy on 4/12/17. + */ + +public enum LoadStatus { + + error("error"), + + over("over"), + + refresh("refresh"), + + retry("retry"); + + private String mStatus; + + LoadStatus(String status) { + mStatus = status; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/baselist/LoadType.java b/app/src/main/java/com/gh/gamecenter/baselist/LoadType.java new file mode 100644 index 0000000000..efc1508ddc --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/baselist/LoadType.java @@ -0,0 +1,20 @@ +package com.gh.gamecenter.baselist; + +/** + * Created by khy on 4/12/17. + */ + +public enum LoadType { + + nomarl("nomarl"), + + refresh("refresh"), + + retry("retry"); + + private String mStatus; + + LoadType(String status) { + mStatus = status; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/baselist/OnListLoadListener.java b/app/src/main/java/com/gh/gamecenter/baselist/OnListLoadListener.java new file mode 100644 index 0000000000..191fa7da9c --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/baselist/OnListLoadListener.java @@ -0,0 +1,29 @@ +package com.gh.gamecenter.baselist; + +import java.util.List; + +import rx.Observable; + +/** + * Created by khy on 2/12/17. + */ + +public interface OnListLoadListener { + + void onLoadDone(); + + void onLoadError(); + + void onLoadMoreError(); + + void onLoadEmpty(); + + void onLoadOver(); + + /** + * 列表数据接口 先放这里吧 + * @param + * @return + */ + Observable> provideDataObservable(); +} diff --git a/app/src/main/java/com/gh/gamecenter/baselist/TestAdapter.java b/app/src/main/java/com/gh/gamecenter/baselist/TestAdapter.java deleted file mode 100644 index 8914653a57..0000000000 --- a/app/src/main/java/com/gh/gamecenter/baselist/TestAdapter.java +++ /dev/null @@ -1,259 +0,0 @@ -package com.gh.gamecenter.baselist; - -import android.content.Context; -import android.support.v7.widget.RecyclerView; -import android.util.DisplayMetrics; -import android.view.View; -import android.view.ViewGroup; -import android.widget.LinearLayout; - -import com.gh.base.OnListClickListener; -import com.gh.common.constant.ItemViewType; -import com.gh.common.util.DisplayUtils; -import com.gh.common.util.ImageUtils; -import com.gh.common.util.NewsUtils; -import com.gh.gamecenter.R; -import com.gh.gamecenter.adapter.viewholder.FooterViewHolder; -import com.gh.gamecenter.adapter.viewholder.NewsImage1ViewHolder; -import com.gh.gamecenter.adapter.viewholder.NewsImage2ViewHolder; -import com.gh.gamecenter.adapter.viewholder.NewsImage3ViewHolder; -import com.gh.gamecenter.entity.NewsEntity; -import com.gh.gamecenter.manager.VisitManager; -import com.gh.gamecenter.retrofit.JSONObjectResponse; -import com.gh.gamecenter.retrofit.RetrofitManager; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Locale; - -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; - -/** - * Created by khy on 10/11/17. - * 测试例子 - */ - -public class TestAdapter extends BaseListAdapter { - - private OnListClickListener mListListener; - - private BaseListPresenterImpl mListPresenter; - - private List mEntityList; - - private boolean mIsLoadOver; - private boolean mIsNetworkError; - - public TestAdapter(Context context, BaseListPresenterImpl objectListPresenter, OnListClickListener listListener) { - super(context); - - mEntityList = new ArrayList<>(); - this.mListPresenter = objectListPresenter; - this.mListListener = listListener; - } - - @SuppressWarnings("unchecked") - @Override - protected void provideListData(List listData) { - if (listData.size() < BaseListPresenterImpl.PAGE_SIZE) { - mIsLoadOver = true; - } - - mIsNetworkError = false; - mEntityList.addAll((Collection) listData); - notifyDataSetChanged(); - } - - @Override - protected void loadError(Throwable e) { - mIsNetworkError = true; - notifyItemChanged(getItemCount() - 1); - } - - @Override - protected void refreshData() { - mEntityList.clear(); - notifyDataSetChanged(); - } - - @Override - public int getItemViewType(int position) { - if (position == mEntityList.size()) { - return ItemViewType.LOADING; - } - NewsEntity newsEntity = mEntityList.get(position); - if ("4x3".equals(newsEntity.getThumbnail().getType()) && newsEntity.getThumbnail().getUrl().size() == 3) { - return ItemViewType.NEWS_IMAGE2; - } - if ("3x1".equals(newsEntity.getThumbnail().getType())) { - return ItemViewType.NEWS_IMAGE3; - } - return ItemViewType.NEWS_IMAGE1; - } - - @Override - public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View view; - switch (viewType) { - case ItemViewType.NEWS_IMAGE1: - view = mLayoutInflater.inflate(R.layout.news_image1_item, parent, false); - return new NewsImage1ViewHolder(view, mEntityList, mListListener); - case ItemViewType.NEWS_IMAGE2: - view = mLayoutInflater.inflate(R.layout.news_image2_item, parent, false); - return new NewsImage2ViewHolder(view, mEntityList, mListListener); - case ItemViewType.NEWS_IMAGE3: - view = mLayoutInflater.inflate(R.layout.news_image3_item, parent, false); - return new NewsImage3ViewHolder(view, mEntityList, mListListener); - case ItemViewType.LOADING: - return new FooterViewHolder(mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false)); - default: - return null; - } - } - - @Override - public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { - switch (getItemViewType(position)) { - case ItemViewType.NEWS_IMAGE1: - initNewsImage1ViewHolder((NewsImage1ViewHolder) holder, position); - break; - case ItemViewType.NEWS_IMAGE2: - initNewsImage2ViewHolder((NewsImage2ViewHolder) holder, position); - break; - case ItemViewType.NEWS_IMAGE3: - initNewsImage3ViewHolder((NewsImage3ViewHolder) holder, position); - break; - case ItemViewType.LOADING: - initFooterViewHolder((FooterViewHolder) holder); - break; - } - } - - @Override - public int getItemCount() { - return mEntityList.size() + 1; - } - - - private void initNewsImage1ViewHolder(final NewsImage1ViewHolder viewHolder, int position) { - - final NewsEntity newsEntity = mEntityList.get(position); - ImageUtils.Companion.display(viewHolder.thumb, newsEntity.getThumbnail().getUrl().get(0)); - viewHolder.title.setText(newsEntity.getTitle()); - int views = newsEntity.getViews(); - if (views == 0) { - viewHolder.read.setVisibility(View.GONE); - } else { - viewHolder.read.setVisibility(View.VISIBLE); - viewHolder.read.setText(String.format(Locale.getDefault(), "阅读 %d", views)); - } - NewsUtils.setNewsType(viewHolder.type, newsEntity.getType(), newsEntity.getPriority(), position); - } - - private void initNewsImage2ViewHolder(final NewsImage2ViewHolder viewHolder, int position) { - - final NewsEntity newsEntity = mEntityList.get(position); - - DisplayMetrics outMetrics = new DisplayMetrics(); - int width = (outMetrics.widthPixels - DisplayUtils.dip2px(mContext, 56)) / 3; - int height = (int) (width * 3 / 4f); - - LinearLayout.LayoutParams lparams1 = new LinearLayout.LayoutParams(width, height); - viewHolder.thumb1.setLayoutParams(lparams1); - - LinearLayout.LayoutParams lparams2 = new LinearLayout.LayoutParams(width, height); - lparams2.leftMargin = DisplayUtils.dip2px(mContext, 8); - viewHolder.thumb2.setLayoutParams(lparams2); - - LinearLayout.LayoutParams lparams3 = new LinearLayout.LayoutParams(width, height); - lparams3.leftMargin = DisplayUtils.dip2px(mContext, 8); - viewHolder.thumb3.setLayoutParams(lparams3); - - viewHolder.title.setText(newsEntity.getTitle()); - - ImageUtils.Companion.display(viewHolder.thumb1, newsEntity.getThumbnail().getUrl().get(0)); - ImageUtils.Companion.display(viewHolder.thumb2, newsEntity.getThumbnail().getUrl().get(1)); - ImageUtils.Companion.display(viewHolder.thumb3, newsEntity.getThumbnail().getUrl().get(2)); - int views = newsEntity.getViews(); - if (views == 0) { - viewHolder.read.setVisibility(View.GONE); - } else { - viewHolder.read.setVisibility(View.VISIBLE); - viewHolder.read.setText(String.format(Locale.getDefault(), "阅读 %d", views)); - } - NewsUtils.setNewsType(viewHolder.type, newsEntity.getType(), newsEntity.getPriority(), position); - } - - private void initNewsImage3ViewHolder(final NewsImage3ViewHolder viewHolder, int position) { - - final NewsEntity newsEntity = mEntityList.get(position); - - viewHolder.title.setText(newsEntity.getTitle()); - ImageUtils.Companion.getInstance().display(viewHolder.thumb, newsEntity.getThumbnail().getUrl().get(0), - mContext.getResources().getDisplayMetrics().widthPixels - DisplayUtils.dip2px(mContext, 40)); - int views = newsEntity.getViews(); - if (views == 0) { - viewHolder.read.setVisibility(View.GONE); - } else { - viewHolder.read.setVisibility(View.VISIBLE); - viewHolder.read.setText(String.format(Locale.getDefault(), "阅读 %d", views)); - } - NewsUtils.setNewsType(viewHolder.type, newsEntity.getType(), newsEntity.getPriority(), position); - } - - private void initFooterViewHolder(FooterViewHolder viewHolder) { - viewHolder.initItemPadding(); - if (mIsNetworkError) { - viewHolder.loading.setVisibility(View.GONE); - viewHolder.hint.setText(R.string.loading_failed_retry); - viewHolder.itemView.setClickable(true); - viewHolder.itemView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - mIsNetworkError = false; - notifyItemChanged(getItemCount() - 1); - mListPresenter.retryLoad(); - } - }); - } else if (mIsLoadOver) { - viewHolder.loading.setVisibility(View.GONE); - viewHolder.hint.setText(R.string.loading_complete); - viewHolder.itemView.setClickable(false); - } else { - viewHolder.loading.setVisibility(View.VISIBLE); - viewHolder.hint.setText(R.string.loading); - viewHolder.itemView.setClickable(false); - } - } - - // 统计新闻阅读量 - public void statNewsViews(final NewsEntity newsEntity, final int position) { - RetrofitManager.getInstance(mContext).getData().postNewsViews(newsEntity.getId()) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new JSONObjectResponse() { - @Override - public void onResponse(JSONObject response) { - if (response.length() != 0) { - try { - if ("success".equals(response.getString("status"))) { - newsEntity.setViews(newsEntity.getViews() + 1); - - notifyItemChanged(position); - - // 更新okhttp缓存数据 - VisitManager.updateOkhttpCache(mContext, newsEntity.getId()); - } - } catch (JSONException e) { - e.printStackTrace(); - } - } - } - }); - } -} diff --git a/app/src/main/java/com/gh/gamecenter/baselist/TestFragment.java b/app/src/main/java/com/gh/gamecenter/baselist/TestFragment.java deleted file mode 100644 index 10f301a5de..0000000000 --- a/app/src/main/java/com/gh/gamecenter/baselist/TestFragment.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.gh.gamecenter.baselist; - -import android.os.Bundle; -import android.support.annotation.Nullable; -import android.support.v7.widget.RecyclerView; -import android.view.View; - -import com.gh.common.util.DataCollectionUtils; -import com.gh.common.util.DataUtils; -import com.gh.common.util.StringUtils; -import com.gh.common.view.VerticalItemDecoration; -import com.gh.gamecenter.NewsDetailActivity; -import com.gh.gamecenter.R; -import com.gh.gamecenter.entity.NewsEntity; -import com.gh.gamecenter.eventbus.EBNetworkState; -import com.gh.gamecenter.retrofit.RetrofitManager; - -import org.greenrobot.eventbus.Subscribe; -import org.greenrobot.eventbus.ThreadMode; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import rx.Observable; - -/** - * Created by khy on 6/11/17. - * 测试例子 - */ - -public class TestFragment extends BaseListFragment { - - private TestAdapter mAdapter; - - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - mAdapter = new TestAdapter(getContext(), mListPresenter, this); - mListPresenter.load(); - } - - @Override - public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - RecyclerView recyclerView = view.findViewById(R.id.list_rv); - recyclerView.addItemDecoration(new VerticalItemDecoration(getContext(), 8, true)); - } - - @Override - protected BaseListAdapter provideAdapter() { - return mAdapter; - } - - @SuppressWarnings("unchecked") - @Override - public Observable> provideDataObservable() { - return RetrofitManager.getInstance(getContext()).getApi().getZiXun(mListPresenter.getListOffset()); - } - - - @Subscribe(threadMode = ThreadMode.MAIN) - public void onEventMainThread(EBNetworkState busNetworkState) { - if (busNetworkState.isNetworkConnected()) { - - } - } - - - @SuppressWarnings("unchecked") - @Override - public void onListClick(View view, int position, Object data) { - List newsList = (List) data; - NewsEntity newsEntity = newsList.get(position); - Map kv = new HashMap<>(); - kv.put("名字", newsEntity.getTitle()); - kv.put("位置", String.valueOf(position + 1)); - DataUtils.onEvent(getContext(), "点击", "资讯-资讯", kv); - - DataCollectionUtils.uploadClick(getContext(), "列表", "资讯-资讯", newsEntity.getTitle()); - - //统计阅读量 - mAdapter.statNewsViews(newsEntity, position); - NewsDetailActivity.startNewsDetailActivity(getContext(), newsEntity, StringUtils.buildString("(资讯:资讯[" + position + "])")); - } -} diff --git a/app/src/main/java/com/gh/gamecenter/fragment/MainFragment.java b/app/src/main/java/com/gh/gamecenter/fragment/MainFragment.java index d08e4df7ca..2dd771a7b3 100644 --- a/app/src/main/java/com/gh/gamecenter/fragment/MainFragment.java +++ b/app/src/main/java/com/gh/gamecenter/fragment/MainFragment.java @@ -8,6 +8,7 @@ import android.view.View; import com.gh.base.SearchBarHint; import com.gh.base.fragment.BaseFragment_ViewPager_Checkable; import com.gh.gamecenter.R; +import com.gh.gamecenter.ask.AskFragment; import com.gh.gamecenter.eventbus.EBReuse; import com.gh.gamecenter.eventbus.EBSkip; import com.gh.gamecenter.eventbus.EBUISwitch; @@ -45,8 +46,9 @@ public class MainFragment extends BaseFragment_ViewPager_Checkable { View mMessageHintIv; public static final int INDEX_GAME = 0; - public static final int INDEX_NEWS = 1; - public static final int INDEX_PERSONAL = 2; + public static final int INDEX_ASK = 1; + public static final int INDEX_NEWS = 2; + public static final int INDEX_PERSONAL = 3; private ArrayList mSearchHintLint; @Override @@ -67,6 +69,7 @@ public class MainFragment extends BaseFragment_ViewPager_Checkable { @Override protected void initFragmentList(List fragments) { fragments.add(new GameWrapperFragment()); + fragments.add(new AskFragment()); fragments.add(new NewsWrapperFragment()); fragments.add(new PersonalFragment()); } diff --git a/app/src/main/res/drawable-xxhdpi/ic_ask_search.png b/app/src/main/res/drawable-xxhdpi/ic_ask_search.png new file mode 100644 index 0000000000000000000000000000000000000000..970f79ce9100f76bc5e9b3d61aa8fef3f80ecc0d GIT binary patch literal 1125 zcmV-r1e*JaP)iC5pxtqjh1lEs8>`L3}|iv=&!Ih3Y~n;!1@o;#RAaE(Aeb zs8vviiXdtQMX`cUDpjObq;?VCX*zw_#>HuxJ7@0PnVWlOO#H)z`DVWJo&W!y*LTjD z4#m-j<+uu$U;t<0lw-eF@Hf84cla3Fu)Bo1OTj#>$A>tIiD^7v;X(Aanfq~cVIzL4 zLvT7z1)FeAQF0wQeAnVBoR#78Cw{=sLf0a^fcY2{x?eqv;ZZz;e{%53g>Jke{jDCw z`?wz$Yy5Khu?{0RTqov7SWvPCun;>_Dm;WOxTrwv`FKKT%{czAxVk{>8Z5?WN=0ws z!V>H0!E-6~?8mKTRIo^`kOR28jNo-}qtGI84_IC#Xpb<6lR-yuWs#swqF-2xl6C(j ztY5j&A#|f;u)Vmn45m$@7vDr2c9>d(o5sCSkZ}x^MzeV=z)umE&3OX!;*Ti69p!S& zg(bq6NiG9dG+TJHY9TMRfM8xcteVpY%@pbr(u&DKV>r7t{BmKg+I8;QMuj#;1s-o9 z!Ms?jn%iqx&K;_!;)*am&lGeD+lNVh2W8}VL#mZ;Z3Dr)ct|zJyV9IGu_F5J<<|0= z7G8|(nDcRrm{NQMr?-$)5hRDgo_bEZ5>7kX!)sc2L3LN_jvYF2e!~8?LBL)Nrv+*Q zc1HHX*r5~K6ZS|(u=9jj={-ITirJ@g56|lJoO8kr#A~z zY##d}yDN5>Bc%6Rnh17MO4)YeP-M@I9Xi`Yqzs%I*<-Q8Y!cHK*}umQvq?-md;J(Y z%qB6HCq9o06IK;wiLIn5R^x8Q_?y)DgYa(eB-Qk<9(aB*ZWZ9w24J`oQ2 zieg=4*InEP)b9PudiE%O%0H<3rs2yh=M60qGWo12DCX5D-uf)(B|_@o3LzC-P(a9a zQM|osGm+z%BP5#3aDA5JF`pX}_Exo-Y!ds0TyIx1tW(g9XQS^P6UJg;#NBaa8A0oy z1FuK*eWt+gQ~{@#*?G(n@^@l literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/ic_ask_select.png b/app/src/main/res/drawable-xxhdpi/ic_ask_select.png new file mode 100644 index 0000000000000000000000000000000000000000..e3edaa3078a8e36dd7e9718ae9762c2f4dd4c0b3 GIT binary patch literal 3014 zcmaJ@dpMM7A09akmDGrY8pDo5%qiw1VNIBrh#{vAW4yz}oJWHWODBy*WQ80mNg^U+ z8&rH6B(WLotVC&swuJPxQp?si+G@W)zP|Ump7(j4-}Sri-|4>I>lFuV^IopMRv!cc zEhqbs0@eGr#Rb+;zq6{K7V6DZxFu8=#9;_UG(G_Gh~`8AP%?`a0|WxJ=piX$M<&ICNh$pMN%p|MC50f}~UM4^c&0uhCVetux; zX#8jfF_7f-IhOk73X2sAxkMyVBoZM+8xb6S3=&Ns5RfPg5`%G6dpHV`*g{&OBU@ng zg@FVJ=zJzu$mFo0i;T1=PJ+-Crq1;55?I`?v~0oWHmMtiOr&vgn__6`TkF00X2yWAOisbCxK5_4~}8A7>Y~uSU0M@q!!Y!`VX7vs?4i zH#yz5NFMhM&o8`bxP#uva=tnZDMW5o>jeRNttbHX`6Qs3#P)Y z3J;k}GLg^L?!j~I0&v~4=aa8$GcweU|7(+>c%Y3J*z;o>|zh+2MsvrO}BR=L|1<1Dc#`y z?WZ=@F)L@TW#{=>iZ7&?9izI0X)e>;TAhi{R;*utb?eEP-$43;K$TQoEFTwrKZf<5?`m|&IV8K> z@vs_<&x9~O(8-`Y=g;e@hp=y>P~Zqt)L0ebg|>qPjZSK7RFZ6{D#lQ@S8H`Hgy~ET zNna6Kc6Xj^0m-*WRb*V43hWSu3Ot5>4lfuUgri^W3+^Lk`GR@Snx&gd13Fqv_aBy& zRJ^^rO?*~V%~v$~M#{+GMi9O;@LoVA(r5l(4-U~R{tRz-u}T0+8kGIgF6+&by8+oD zdjh@nWu`xG6 zU82m|I?Bn@Xcu4VMCSt*GMavJlio>(e4_WoEUuC~oG_7SESch-I6>bTlf(_o!B<-6 z9xC~jbGmRwTq}rq+PPiD4-T`Fu!6v1dWr99|0cGqF}N$vFA>Nz!<~`7dGPv~A>{hQ zOfyQPnOWZQ>Uh4&>lX_`m_@$UO|y*HifHraJOMXJZzia%M}o^qf*bYe+AVwcF(@@P z@a&Q%uK+iRObs3uV`)Bya{TGS6_E_PXR#2Qp(}5a3e(2iwioLAUE}$cl$+JHQ~ffp zo{qsAqO=5KUbx_rBSR)Lj+B7%Eu1^%t!MRcgmkA3?+Kef_-{$POBwaFwevoq;9<500IuW99_u9e~1Hy#c|otW*BcE2kcyY4|; z;+UJ!s^^k6zAIcKq^ChUCqCguSIrK<9mzR4-lR(K4zE_ha7t{IU)z?prKuT_)|~wHthMN@F_X^Gmat>Uy=m=wR_n+kS8AVEksDwL$MB$MP5Z-_o-2CDKTn zVJWfA_rYt!!pEzPX@ixzmHEkpwx4j64sx$~rPPuntFNUvbj=@wh?M6}0jnZHW-dh6 zdsi)uIK3`nXDqI?_=WP$=?yX5MDPi-%jUcJs1g4wYkzHa#7+>Fhl|4Xb32<|uS~g0 z-zjiB*ouPm_Zuqq?%KLtUZ7WaAxfb5%cJ$-%4!9AAvtpOT$&=2?4k53x@(6<(CrQU zitk)#!&Su}NYCk%y==hpUQn;zZ+Dz7?<&5O?&fbP$AfMc{*e$2v54O!pF9Nj7wzbZ z3py$hqy$&+AG69|qa7xkbqjhdkUkztB6;%iZ*u;uYEx?%2>0U3gG7@vuSAW-5=%Hn zsUYRG8Vs+uKB$D}SE^3#MbnncN|JjQTDN~s#bfrh=+$L8JIE69OZh+b5)iJf+W1vt zhuIB%4e^tY(i$`B;``x4wDHKGK-~dF1+rTN8#cbKC`* zxX7xI)Gn387Syi?|31loX6p9itWLtJhkhQ4*YIl@IXjcHI>dds*~dqIxON&MXU`fs zHp}rVY#Sh>2CI3!=ls>5m<+4u!}co1sFs<4+nDkwluOUclOK31BO8y1Bb%_^e~#$f zzkcRU`0=Cn-Z$*LYX3HqBWrdqKPJ1{|0El_&3+wwq4#ASq#0`t9fCdaJ?2+iW1q`V zxUX6!q(Q?dNgyuBIyW0W> zfQ-M&@Dg3fL7t6r=(6gn`yklz%8@STxjVP}bRI^$ZjIy-o9Ltq)*}63S<1jv)5eZV z-8XU|yksupTpJ~}Vb{|mM^G=#b|Iw@>6+(uhk_$6{#p+%+I2o#^8K_xMoq=9{9UvP z+8BpG4S3sjKK?^9HHYyy1Y;x#>!nyP?O`sR?YRF&o7-~kVAR~c6LCQf2CVa!r3%Si z8E>PeQ~d$Dn@vrmz5mqRpdmn15^gcrdF=;t5ouH+ckzopkzH~dR==|YK6WbSu`V7< qew9-QM^GZqNS%1h%hn(DP#{4R1`C^;DO~)sCU4nBs{MY?;r{@~E)bCb literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/ic_ask_selectgame.png b/app/src/main/res/drawable-xxhdpi/ic_ask_selectgame.png new file mode 100644 index 0000000000000000000000000000000000000000..034150ff684733dcc1dc816d1c1b79d73bd54532 GIT binary patch literal 518 zcmV+h0{Q)kP)ujdNJW$uT?kakC*mIELA-=0c2ev}Sg(1-}d37DWHY zbPJl#n>fqvgr<->zOokU{d>1;HAw^W7NRG{8Z zJjY_MKUm*xp)B$}xS^S*aTPDHnBgI=1`3XH2D7+5X1<`ROq=2~j&#Z*9|}K-t$gbB z2Zy#Bltum#MZgj3`Tg$VO+#X% ztklewTkw09;SwIH%7>Xi!Ebnp>oq&`_@er^-yi7ruW4NP3zH8>Z9zO3!2kdN07*qo IM6N<$g37h@9{>OV literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/ic_ask_unselect.png b/app/src/main/res/drawable-xxhdpi/ic_ask_unselect.png new file mode 100644 index 0000000000000000000000000000000000000000..0214e8cc40db7a0a5b849c08a60c3425937daa78 GIT binary patch literal 2985 zcmaJ@XH-+m7LK4)K_k+n7z2vZlF(A1W+p6|?>Gc$Yb@7v$(z1Lai&{iK04YgHj002P4 z%M;@#Uwsy)ijw@DSqw6gFZx_;5Z9j(#f>Mj$pH6AMg$q;MI%O&{m8_~1eS#C1OO}#I z7XyaOA+ae;E`>n{Eie)z7(A{sSg!QP6==-gv~t(fdD%IRObwGQ^L}Ver@_dEuf=7D6#mXf~P1Wv~Mn4C=2eZjE7Z8Jrjf z6NE-DWDO2lk0+8S^abOF?#qJm55>M^Q zUb;e2G+~;2XaBy4HH7sztGhABM%(#4R=S0F@c}cz18tpwM}5-;Nl%n zm68LIdQii{@dz#z@V9~^CVoso)A#DdN6nX{#h!wkd}RZ`DFv%NLksGV~ z&~Hw&AW&6A`;edcOxBW7w}%s^jBb6;V8G5ag}e*rKJS}dpXy)h9hkeR-a0!zEo8-9 z`hXO8tHN5u(V|JPZ2PT(o3}0CMsGw2yGn~}N&`~o>MS=2c>1W%+$yCWD~gesKW8cQ z?(1oqA#zloMgy6K*51lZ_YiMuko#<;w({E8uNBrasCp6)=e-i*bbx$K5u8M2&39uvobA$;k|SvM)LBL49s4OVKa@CrT~Wrs5^1 zZ=k+Wq7!=IbGrv_NMgx5XVz}6oz91lE3I*k^y!UJc%Jyd!S?2}ovL~F+uCvxI`qFdpX`(l)LPz| z!5Uw?mN7sdX;0j6uf!;r+MHp`iZ1ClF*cBDL^RQNM>NJYgeq07`KGjt>_lsf`_!!J z;CZ2Ev`4SZ^U9O7&W4TQ8zwE1OvkS;MBOE;X(W-e7QuG}AVNM^oLmcWQl%zxdr5zqD?A z|GjQrb{BwgcjTlj&IH=ye)arlSvgj9@?-E{s31v1?wi-;zOu=#DmTFwUnBVYpl4H) z%no=#wL$9ky=+|Yxm6?U!aZceG#KFI<{q&pnzy?n6G2O{n;b5Nii`IFdr}9rGAx=h zj@3U$>k~%XMOSTv776rgVOC?tU|M(x%2SRa@x=EZX7&_rQwWxjUX04_f>-LTS<>mT050suNhTS`F5;ynIu>@-LBnj{OOzLSNdHuf+Fke zS>=mD3e`qV?r9uJf6zWNR4H2Iw8iM7=zXd8nJZj_FGX)>eUzZ&Qs9xE40X8q&FGF8 zQdsPn%q(@Y4~>$u8!B!XtxXAk>JhTGfXW}ImV6zc8lbBJ^!F*+gjZ^8I{-oQ@5r*^ z%1oA)y}Rg?X3;Re=U8Udl#m)oA0kYDT&>yLlnD*)q|!J=Lm9`in}D`~!lv7{305@mwTW|)tp<(6kH#a}qd1|b0sxu6^RwqNc|U>A(_YF%mP%XsA+$o_PzN< zM;`U+*M+_AKMKMT)(aFVv_UTl_IZih>bmVhrwl|wv-@bZh=S95aW(qWiAqG<*F!{* z^pr0H9vEWrwaP&BcDf@5_mR82dhp;QH@z?`86&8^qFv=PJ?6=&l+hMdc254C=)`f{mGS242t{`*pO>O;6)D}7FB?Q~g~a#Y@!*40u}a}bBVn*>%5LiET(s5&7LnlB#0gDG8-Ju(e$2>9X@2dHUW=` zeymud_MoNNJbySr@sn!hiq52?iy=B4c~*y0Hx)WHK2{FtfLT|s4BEMD_qu{uqWN_5 zx4_;MX + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/ask_item.xml b/app/src/main/res/layout/ask_item.xml new file mode 100644 index 0000000000..27c57d825c --- /dev/null +++ b/app/src/main/res/layout/ask_item.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_ask.xml b/app/src/main/res/layout/fragment_ask.xml new file mode 100644 index 0000000000..19881f0e43 --- /dev/null +++ b/app/src/main/res/layout/fragment_ask.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_main.xml b/app/src/main/res/layout/fragment_main.xml index c296b80235..c1309cb9c0 100644 --- a/app/src/main/res/layout/fragment_main.xml +++ b/app/src/main/res/layout/fragment_main.xml @@ -50,6 +50,32 @@ + + + + + + + + + #1668d0 - #59d3ff + #59d3ff - #717171 + #717171 - #676767 + #676767 - #f8f8f8 + #f8f8f8 - #FF4E00 + #FF4E00 - #175aa3 + #175aa3 - #60d6d5ff + #60d6d5ff - #949494 + #949494 - #454545 + #454545 - #e9e9e9 + #e9e9e9 - #ff8814 + #ff8814 - #ecfaff + #ecfaff + + @android:color/black #ff4147 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1b60469e13..350aa5aac9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -431,5 +431,8 @@ 未填写 请输入正确的链接 登录成功 + 问答 + 精选 + 问题