AndroidはRecyclerViewのドロップダウン・リフレッシュとアップロードを実現
需要
先に効果図をアップロードし、Material Designスタイルのドロップダウンリフレッシュとアップロードを追加します.
ソースアドレス(starへようこそ)https://github.com/studychen/SeeNewsV2
RecyclerViewについてまだ詳しくない場合は、ListViewの代わりにこのAndroid Material Designが学んだRecyclerViewを参照してください.
本リンクhttp://blog.csdn.net/never_cxb/article/details/50759109転載は出典を明記してください
ドロップダウン・リフレッシュ
効果図
プルアップ時に円形アニメーションがあり、ロードデータをリフレッシュします.
構想
Google公式の
リストRecyclerViewのxmlレイアウト
元のRecyclerViewにSwipeRefreshLayoutの親レイアウトを追加
JAvaコード
ここにはいくつかの注意点があります.
ドロップダウン・リフレッシュ後、AsyncTaskを使用して、現在のRecyclerViewの最初のItemのidに基づいてより多くのデータをロードします.
データのロードが完了したら、
リフレッシュ後に0個のレコードが得られた場合、
初めてページに入るとingをロードしたアニメーションが表示されます
効果は次のとおりです.
見ましたhttp://stackoverflow.com/questions/26858692/swiperefreshlayout-setrefreshing-not-showing-indicator-initiallyの解答は、次のコードに変更して、初期状態でアニメーション表示をロードします.
アップロード
RecyclerViewディスプレイリストは一般的なニーズですが、データが多い場合、どのようにページングロードを実現しますか?
例えば筆者の項目では,まず15のニュースをロードし,最後までスライドしたときに15のニュースをロードする.
効果図
構想
RecyclerViewの下部にFooterのViewHolderを追加し、データのロードが完了して下部のViewHolderを取り出します.
下部Footerのxmlレイアウトファイル
簡単です.ProgressBarです.本プロジェクトでは、Material DesignのためにオープンソースProgressBarを使用しています.https://github.com/Todd-Davies/ProgressWheelあ、オリジナルのProgressBarも使えます.
下部FooterのViewHolder
FragmentでRecyclerViewにスライドリスニングを追加
totalItemCount<(lastVisibleItem+Constant.VISIBLE_THRESHOLD)
例えば15個のItemが現在13個目に達していますVISIBLE_THRESHOLDは3総数が最後の+しきい値より小さいように設定し、より多くのニュースデータをロードし、同時にloadingをtrueとマークする.
Fragmentで下部Footerを制御する
私たちは依然としてAsyncTaskを使用しています.
注意
データのロードが完了したら、一番下のFooterを
さらに
Override RecyclerView.AdapterのgetItemViewタイプ
本稿では,UIの美しさのために,ニュースを3枚以上,3枚未満の2種類に分け,それに応じて異なるTypeとViewHolderを返す.
Override RecyclerView.AdapterのonCreateViewHolder
この方法では、
Override RecyclerView.AdapterのonBindViewHolder
どのタイプのViewHolderであるかをinstanceofで判断し、コントロールにデータを割り当て、バインドします.
注意:Footerはnullで表示されているので、NullPointerExceptionを防ぐために、まずifでFooterView Holderの状況を処理しました.
ドロップダウン・リフレッシュとアップロードのソース・アドレス(starを歓迎)https://github.com/studychen/SeeNewsV2
本リンクhttp://blog.csdn.net/never_cxb/article/details/50759109転載は出典を明記してください
いくつかの穴
RecyclerView setLayoutManagerに注意してください.そうしないと、RecyclerViewは表示されない可能性があります.
参考記事 LoadMore RecyclerView with progress bar showing at bottom Android Material Design学習のRecyclerView代替ListView Swipe/Pull to Refresh for Android RecyclerView (or any other vertically scrolling view)
先に効果図をアップロードし、Material Designスタイルのドロップダウンリフレッシュとアップロードを追加します.
ソースアドレス(starへようこそ)https://github.com/studychen/SeeNewsV2
RecyclerViewについてまだ詳しくない場合は、ListViewの代わりにこのAndroid Material Designが学んだRecyclerViewを参照してください.
本リンクhttp://blog.csdn.net/never_cxb/article/details/50759109転載は出典を明記してください
ドロップダウン・リフレッシュ
効果図
プルアップ時に円形アニメーションがあり、ロードデータをリフレッシュします.
構想
Google公式の
android.support.v4.widget.SwipeRefreshLayout
を使用リストRecyclerViewのxmlレイアウト
元のRecyclerViewにSwipeRefreshLayoutの親レイアウトを追加
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/listBackground"
android:orientation="vertical">
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swiperefreshlayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.RecyclerView
android:id="@+id/rcv_article_origin"
android:layout_width="match_parent"
android:layout_height="match_parent" />
android.support.v4.widget.SwipeRefreshLayout>
LinearLayout>
JAvaコード
ここにはいくつかの注意点があります.
setColorSchemeColors()
は円形アニメーションの色を制御し、最大4つ設定できます.setOnRefreshListener
ドロップダウン・リフレッシュのコールバック・イベントを設定します.ドロップダウン・リフレッシュ後、AsyncTaskを使用して、現在のRecyclerViewの最初のItemのidに基づいてより多くのデータをロードします.
データのロードが完了したら、
setRefreshing(false);
を使用してアニメーションをキャンセルします.リフレッシュ後に0個のレコードが得られた場合、
を提示する.>0個のデータが得られたら、RecyclerViewにデータを加算mSwipeRefreshLayout.setColorSchemeColors(Color.RED, Color.BLUE);
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new MoreArticleTask().execute(mAdapter.getTopArticleId());
}
});
// Integer
// id
class MoreArticleTask extends AsyncTask<Integer, Void, List<SimpleArticleItem>> {
@Override
protected List doInBackground(Integer... params) {
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return getMoreById(mColumn, params[0]);
}
@Override
protected void onPostExecute(List simpleArticleItems) {
super.onPostExecute(simpleArticleItems);
if (mSwipeRefreshLayout != null) {
mSwipeRefreshLayout.setRefreshing(false);
}
// ,
if (simpleArticleItems == null || simpleArticleItems.size() == 0) {
Snackbar.with(mActivity.getApplicationContext()) // context
.text(mActivity.getResources().getString(R.string.list_more_data)) // text to display
.duration(Snackbar.SnackbarDuration.LENGTH_SHORT) // make it shorter
.show(mActivity); // activity where it is displayed
} else {
mArticleList.addAll(simpleArticleItems);
mAdapter.notifyDataSetChanged();
}
}
}
初めてページに入るとingをロードしたアニメーションが表示されます
効果は次のとおりです.
mSwipeRefreshLayout.setRefreshing(true);
を直接使用してアニメーションの初期状態をロードしても表示されません.見ましたhttp://stackoverflow.com/questions/26858692/swiperefreshlayout-setrefreshing-not-showing-indicator-initiallyの解答は、次のコードに変更して、初期状態でアニメーション表示をロードします.
mSwipeRefreshLayout.post(new Runnable() {
@Override
public void run() {
mSwipeRefreshLayout.setRefreshing(true);
new MoreArticleTask().execute(mAdapter.getTopArticleId());
}
});
アップロード
RecyclerViewディスプレイリストは一般的なニーズですが、データが多い場合、どのようにページングロードを実現しますか?
例えば筆者の項目では,まず15のニュースをロードし,最後までスライドしたときに15のニュースをロードする.
効果図
構想
RecyclerViewの下部にFooterのViewHolderを追加し、データのロードが完了して下部のViewHolderを取り出します.
下部Footerのxmlレイアウトファイル
簡単です.ProgressBarです.本プロジェクトでは、Material DesignのためにオープンソースProgressBarを使用しています.https://github.com/Todd-Davies/ProgressWheelあ、オリジナルのProgressBarも使えます.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:wheel="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.pnikosis.materialishprogress.ProgressWheel
android:id="@+id/rcv_load_more"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center_horizontal"
wheel:matProg_barColor="@color/accent"
wheel:matProg_progressIndeterminate="true" />
LinearLayout>
下部FooterのViewHolder
/**
*
*/
class FooterViewHolder extends RecyclerView.ViewHolder {
@InjectView(R.id.rcv_load_more)
ProgressWheel rcvLoadMore;
public FooterViewHolder(View itemView) {
super(itemView);
ButterKnife.inject(this, itemView);
}
}
FragmentでRecyclerViewにスライドリスニングを追加
layoutManager.getItemCount()
現在のRecyclerViewにおけるItemの総数を得ることができるlayoutManager.findLastVisibleItemPosition()
最後に見えるItemの位置positionを得るtotalItemCount<(lastVisibleItem+Constant.VISIBLE_THRESHOLD)
例えば15個のItemが現在13個目に達していますVISIBLE_THRESHOLDは3総数が最後の+しきい値より小さいように設定し、より多くのニュースデータをロードし、同時にloadingをtrueとマークする.
private boolean loading = false;
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mRecyclerView.setLayoutManager(new LinearLayoutManager(mActivity));
mAdapter = new OriginArticleAdapter(mActivity, mArticleList);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
int totalItemCount = layoutManager.getItemCount();
int lastVisibleItem = layoutManager.findLastVisibleItemPosition();
if (!loading && totalItemCount < (lastVisibleItem + Constant.VISIBLE_THRESHOLD)) {
new ArticleTask(mActivity).execute(mAdapter.getBottomArticleId());
loading = true;
}
}
});
}
Fragmentで下部Footerを制御する
私たちは依然としてAsyncTaskを使用しています.
注意
onPreExecute()
はmArticleListにnullタグFooterを追加し、最初にページにアクセスした場合(mArticleListが空の場合)Footerを追加する必要はありません.データのロードが完了したら、一番下のFooterを
mArticleList.remove(mArticleList.size() - 1);
で削除します.さらに
mArticleList.addAll(moreArticles);
で新しいニュースデータを追加し、mAdapter.notifyDataSetChanged();
でRecyclerViewに通知する.Adapterにはデータの変更があります.private List mArticleList = new ArrayList();
class ArticleTask extends AsyncTask<Integer, Void, List<SimpleArticleItem>> {
private Context mContext;
public ArticleTask(Context context) {
mContext = context;
}
/**
* Runs on the UI thread before {@link #doInBackground}.
*/
@Override
protected void onPreExecute() {
super.onPreExecute();
if (mArticleList != null && mArticleList.size() > 0) {
mArticleList.add(null);
// notifyItemInserted(int position), position
// ,
// , , 。
mAdapter.notifyItemInserted(mArticleList.size() - 1);
}
}
/**
* @param params aid
* @return
*/
@Override
protected List doInBackground(Integer... params) {
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return getArticleList(mColumn, params[0]);
}
@Override
protected void onPostExecute(final List moreArticles) {
//
super.onPostExecute(moreArticles);
if (mArticleList.size() == 0) {
mArticleList.addAll(moreArticles);
mAdapter.notifyDataSetChanged();
} else {
// footer
mArticleList.remove(mArticleList.size() - 1);
mArticleList.addAll(moreArticles);
mAdapter.notifyDataSetChanged();
loading = false;
}
}
}
Override RecyclerView.AdapterのgetItemViewタイプ
extends RecyclerView.Adapter
nullの場合、FooterのTypeに戻ります.そうでなければ、通常のニュースのTypeに戻ります.本稿では,UIの美しさのために,ニュースを3枚以上,3枚未満の2種類に分け,それに応じて異なるTypeとViewHolderを返す.
public final static int TYPE_MULTI_IMAGES = 2; //
public final static int TYPE_FOOTER = 3;// -- loading_more
public final static int TYPE_NORMAL = 1; //
@Override
public int getItemViewType(int position) {
SimpleArticleItem article = articleList.get(position);
if (article == null) {
return TYPE_FOOTER;
} else if (article.getImageUrls().length >= 3) {
return TYPE_MULTI_IMAGES;
} else {
return TYPE_NORMAL;
}
}
Override RecyclerView.AdapterのonCreateViewHolder
この方法では、
switch (viewType)
を使用して異なるxmlレイアウトファイルおよびViewHolderを返す@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
RecyclerView.ViewHolder vh;
View view;
switch (viewType) {
// viewholder_article_simple
default:
case TYPE_NORMAL:
view = mLayoutInflater.inflate(
R.layout.item_article_normal, parent, false);
vh = new ItemArticleViewHolder(view);
return vh;
case TYPE_FOOTER:
view = mLayoutInflater.inflate(
R.layout.recyclerview_footer, parent, false);
vh = new FooterViewHolder(view);
return vh;
case TYPE_MULTI_IMAGES:
view = mLayoutInflater.inflate(
R.layout.item_article_multi_images, parent, false);
vh = new MultiImagesViewHolder(view);
return vh;
}
}
Override RecyclerView.AdapterのonBindViewHolder
どのタイプのViewHolderであるかをinstanceofで判断し、コントロールにデータを割り当て、バインドします.
注意:Footerはnullで表示されているので、NullPointerExceptionを防ぐために、まずifでFooterView Holderの状況を処理しました.
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
// article null, footer
if (holder instanceof FooterViewHolder) {
((FooterViewHolder) holder).rcvLoadMore.spin();
return;
}
SimpleArticleItem article = articleList.get(position);
String[] imageUrls = article.getImageUrls();
if (holder instanceof ItemArticleViewHolder) {
ItemArticleViewHolder newHolder = (ItemArticleViewHolder) holder;
newHolder.rcvArticleTitle.setText(article.getTitle());
newHolder.rcvArticleDate.setText(article.getPublishDate());
// 3 1
if (imageUrls.length > 0) {
newHolder.rcvArticlePhoto.setImageURI(Uri.parse(Constant.BUCKET_HOST_NAME
+ imageUrls[0]));
} else {
newHolder.rcvArticlePhoto.setImageURI(Uri.parse(ApiUrl.randomImageUrl(article.getId())));
}
// int , String
newHolder.rcvArticleReadtimes.setText(" : " + article.getReadTimes());
newHolder.rcvArticleSummary.setText(article.getSummary());
} else {
MultiImagesViewHolder newHolder = (MultiImagesViewHolder) holder;
newHolder.articleTitle.setText(article.getTitle());
newHolder.articlePic1.setImageURI(Uri.parse(Constant.BUCKET_HOST_NAME + imageUrls[0]));
newHolder.articlePic2.setImageURI(Uri.parse(Constant.BUCKET_HOST_NAME + imageUrls[1]));
newHolder.articlePic3.setImageURI(Uri.parse(Constant.BUCKET_HOST_NAME + imageUrls[2]));
newHolder.countPics.setText(" : " + imageUrls.length);
newHolder.countRead.setText(" : " + article.getReadTimes());
}
}
ドロップダウン・リフレッシュとアップロードのソース・アドレス(starを歓迎)https://github.com/studychen/SeeNewsV2
本リンクhttp://blog.csdn.net/never_cxb/article/details/50759109転載は出典を明記してください
いくつかの穴
RecyclerView setLayoutManagerに注意してください.そうしないと、RecyclerViewは表示されない可能性があります.
// 1. get a reference to recyclerView
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.list);
// 2. set layoutManger
recyclerView.setLayoutManager(new LinearLayoutManager(this));
参考記事