新增通用列表模块,问答精选
This commit is contained in:
@ -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;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
93
app/src/main/java/com/gh/gamecenter/ask/AskFragment.java
Normal file
93
app/src/main/java/com/gh/gamecenter/ask/AskFragment.java
Normal file
@ -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<Fragment> 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);
|
||||
}
|
||||
}
|
||||
98
app/src/main/java/com/gh/gamecenter/ask/AskHotAdapter.java
Normal file
98
app/src/main/java/com/gh/gamecenter/ask/AskHotAdapter.java
Normal file
@ -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<NewsEntity> mEntityList;
|
||||
|
||||
public AskHotAdapter(Context context, OnListClickListener listClickListener) {
|
||||
super(context);
|
||||
mListClickListener = listClickListener;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected <T> void provideListData(List<T> listData) {
|
||||
mEntityList = (List<NewsEntity>) 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;
|
||||
}
|
||||
}
|
||||
48
app/src/main/java/com/gh/gamecenter/ask/AskHotFragment.java
Normal file
48
app/src/main/java/com/gh/gamecenter/ask/AskHotFragment.java
Normal file
@ -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<List<NewsEntity>> 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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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 <T> void provideListData(List<T> listData);
|
||||
|
||||
protected abstract void loadError(Throwable e);
|
||||
protected abstract void loadChange(LoadStatus status);
|
||||
|
||||
protected abstract void refreshData();
|
||||
public boolean isNetworkError() {
|
||||
return mIsNetworkError;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 <T>
|
||||
*/
|
||||
<T> void LoadFinish(List<T> dataList);
|
||||
|
||||
/**
|
||||
* 加载失败,注意首次加载和分页加载
|
||||
*
|
||||
* @param e
|
||||
*/
|
||||
void LoadError(Throwable e);
|
||||
|
||||
/**
|
||||
* 提供数据源头
|
||||
*
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
<T> Observable<List<T>> provideDataObservable();
|
||||
|
||||
/**
|
||||
* 列表 RecyclerView Adapter
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
BaseListAdapter provideRecyclerAdapter();
|
||||
|
||||
}
|
||||
|
||||
interface BaseListPresenter {
|
||||
|
||||
/**
|
||||
* 加载数据, 无论是初始化还是分页都只用一个(注意控制 ListSize-offset)
|
||||
*/
|
||||
void load();
|
||||
|
||||
/**
|
||||
* 加载重试
|
||||
*/
|
||||
void retryLoad();
|
||||
|
||||
/**
|
||||
* 提供 Fragment View 可以不传, 不传的话自己搞
|
||||
*
|
||||
* @param view Fragment View
|
||||
*/
|
||||
void provideView(View view);
|
||||
|
||||
}
|
||||
}
|
||||
@ -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 <T> void LoadFinish(List<T> dataList) {
|
||||
provideAdapter().provideListData(dataList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void LoadError(Throwable e) {
|
||||
provideAdapter().loadError(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseListAdapter provideRecyclerAdapter() {
|
||||
return provideAdapter();
|
||||
}
|
||||
}
|
||||
@ -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<List<Object>>() {
|
||||
@Override
|
||||
public void onNext(List<Object> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
144
app/src/main/java/com/gh/gamecenter/baselist/ListFragment.java
Normal file
144
app/src/main/java/com/gh/gamecenter/baselist/ListFragment.java
Normal file
@ -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<T> extends BaseFragment implements
|
||||
Observer<List<T>>,
|
||||
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<T> 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);
|
||||
}
|
||||
}
|
||||
123
app/src/main/java/com/gh/gamecenter/baselist/ListRepository.java
Normal file
123
app/src/main/java/com/gh/gamecenter/baselist/ListRepository.java
Normal file
@ -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<T> {
|
||||
|
||||
public final static int PAGE_SIZE = 20;
|
||||
|
||||
private MutableLiveData<List<T>> mListLiveData;
|
||||
private List<T> 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<List<T>> listObservable = mLoadListener.provideDataObservable();
|
||||
|
||||
if (mIsLoading || mIsOver || mIsNetworkError || listObservable == null) return;
|
||||
|
||||
mIsLoading = true;
|
||||
|
||||
listObservable
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Response<List<T>>() {
|
||||
@Override
|
||||
public void onResponse(List<T> 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<T> listData) {
|
||||
mCacheListData.addAll(listData);
|
||||
mListLiveData.postValue(mCacheListData);
|
||||
}
|
||||
|
||||
public LiveData<List<T>> getListLiveData() {
|
||||
if (mCacheListData != null) {
|
||||
mListLiveData.postValue(mCacheListData);
|
||||
}
|
||||
return mListLiveData;
|
||||
}
|
||||
}
|
||||
@ -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<T> extends AndroidViewModel {
|
||||
|
||||
private ListRepository mRepository;
|
||||
|
||||
private LiveData<List<T>> mLiveListData;
|
||||
|
||||
|
||||
public ListViewModel(Application application, ListRepository repository) {
|
||||
super(application);
|
||||
mRepository = repository;
|
||||
mLiveListData = mRepository.getListLiveData();
|
||||
|
||||
}
|
||||
|
||||
public LiveData<List<T>> 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 extends ViewModel> T create(Class<T> modelClass) {
|
||||
//noinspection unchecked
|
||||
return (T) new ListViewModel(mApplication, mRepository);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
22
app/src/main/java/com/gh/gamecenter/baselist/LoadStatus.java
Normal file
22
app/src/main/java/com/gh/gamecenter/baselist/LoadStatus.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
20
app/src/main/java/com/gh/gamecenter/baselist/LoadType.java
Normal file
20
app/src/main/java/com/gh/gamecenter/baselist/LoadType.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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 <T>
|
||||
* @return
|
||||
*/
|
||||
<T> Observable<List<T>> provideDataObservable();
|
||||
}
|
||||
@ -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<NewsEntity> 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 <T> void provideListData(List<T> listData) {
|
||||
if (listData.size() < BaseListPresenterImpl.PAGE_SIZE) {
|
||||
mIsLoadOver = true;
|
||||
}
|
||||
|
||||
mIsNetworkError = false;
|
||||
mEntityList.addAll((Collection<? extends NewsEntity>) 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -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<List<NewsEntity>> 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<NewsEntity> newsList = (List<NewsEntity>) data;
|
||||
NewsEntity newsEntity = newsList.get(position);
|
||||
Map<String, Object> 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 + "])"));
|
||||
}
|
||||
}
|
||||
@ -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<String> mSearchHintLint;
|
||||
|
||||
@Override
|
||||
@ -67,6 +69,7 @@ public class MainFragment extends BaseFragment_ViewPager_Checkable {
|
||||
@Override
|
||||
protected void initFragmentList(List<Fragment> fragments) {
|
||||
fragments.add(new GameWrapperFragment());
|
||||
fragments.add(new AskFragment());
|
||||
fragments.add(new NewsWrapperFragment());
|
||||
fragments.add(new PersonalFragment());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user