RecyclerView
を使用し、10個のバッチでAPIからオブジェクトをフェッチしています。ページネーションには、 EndlessRecyclerOnScrollListener
を使用します。
すべて正常に動作しています。次は、APIによってオブジェクトの次のバッチが取得される間に、リストの下部に進行状況スピナーを追加するだけです。 Google Playストアアプリのスクリーンショットは、ProgressBar
にRecyclerView
が表示されています。
問題は、RecyclerView
もEndlessRecyclerOnScrollListener
も、次のオブジェクトのバッチがフェッチされている間、下部にProgressBar
を表示するための組み込みのサポートがないことです。
私はすでに次の答えを見てきました。
1。ProgressBar
grid にフッターとして不定のRecyclerView
を挿入します。
2。下部のRecyclerView
でEndless Scroll ProgressBar
にアイテムを追加する 。
私はそれらの答えに満足していません(両方とも同じ人による)。これには、ユーザーがスクロールしている途中でnull
オブジェクトをデータセットにシューホーンし、次のバッチが配信された後にそれを取り出すことが含まれます。それはハックのように見え、適切に機能するかどうかわからない主要な問題を回避します。そして、それはリストにちょっとした不快感と歪みを引き起こします
SwipeRefreshLayout
を使用することは、ここでは解決策ではありません。 SwipeRefreshLayout
は、先頭からプルしてnewestアイテムを取得することを伴いますが、いずれにしても進行状況ビューは表示されません。
誰かがこれに良い解決策を提供できますか? Googleが独自のアプリにこれをどのように実装しているかに興味があります(Gmailアプリにもあります)。これが詳細に示されている記事はありますか?すべての回答とコメントを歓迎します。ありがとうございました。
その他の参照:
1。RecyclerView
によるページネーション。 (素晴らしい概要...)
2。RecyclerView
ヘッダーとフッター 。 (同じものをもっと...)
HERE IS SIMPLER AND CLEANER APPROACH。
このコードパスガイド からエンドレススクロールを実装し、次の手順に従います。
1。 RecyclerViewの下にプログレスバーを追加します。
<Android.support.v7.widget.RecyclerView
Android:id="@+id/rv_movie_grid"
Android:layout_width="0dp"
Android:layout_height="0dp"
Android:paddingBottom="50dp"
Android:clipToPadding="false"
Android:background="@Android:color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</Android.support.v7.widget.RecyclerView>
<ProgressBar
Android:id="@+id/progressBar"
style="?android:attr/progressBarStyle"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:visibility="invisible"
Android:background="@Android:color/transparent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
ここでAndroid:paddingBottom = "50dp"およびAndroid:clipToPadding = "false"非常に重要です。
2。進行状況バーへの参照を取得します。
progressBar = findViewById(R.id.progressBar);
3。進行状況バーを表示および非表示にするメソッドを定義します。
void showProgressView() {
progressBar.setVisibility(View.VISIBLE);
}
void hideProgressView() {
progressBar.setVisibility(View.INVISIBLE);
}
これを行う別の方法があります。
listItems.size() + 1
を返しますgetItemViewType()
のposition >= listItems.size()
にVIEW_TYPE_LOADING
を返します。これにより、ローダーはリサイクラビューリストの最後にのみ表示されます。このソリューションの唯一の問題は、最後のページに到達した後でもローダーが表示されるため、アダプターにx-pagination-total-count
を保存することを修正するためです。次に、ビュータイプを返すように条件を変更します
(position >= listItem.size())&&(listItem.size <= xPaginationTotalCount)
。
今このアイデアを思いついたのですが、どう思いますか?
ここに偽のアイテムを追加せずに回避策があります(Kotlinではシンプルですが):
アダプターに以下を追加します。
private var isLoading = false
private val VIEWTYPE_FORECAST = 1
private val VIEWTYPE_PROGRESS = 2
override fun getItemCount(): Int {
if (isLoading)
return items.size + 1
else
return items.size
}
override fun getItemViewType(position: Int): Int {
if (position == items.size - 1 && isLoading)
return VIEWTYPE_PROGRESS
else
return VIEWTYPE_FORECAST
}
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): RecyclerView.ViewHolder {
if (viewType == VIEWTYPE_FORECAST)
return ForecastHolder(LayoutInflater.from(context).inflate(R.layout.item_forecast, parent, false))
else
return ProgressHolder(LayoutInflater.from(context).inflate(R.layout.item_progress, parent, false))
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder?, position: Int) {
if (holder is ForecastHolder) {
//init your item
}
}
public fun showProgress() {
isLoading = true
}
public fun hideProgress() {
isLoading = false
}
これで、API呼び出しの前にshowProgress()
を簡単に呼び出すことができます。およびhideProgress()
API呼び出しが行われた後。
進行状況ビューホルダーをアダプターに追加するというアイデアは気に入っていますが、必要なものを取得するためのsomeいロジック操作につながる傾向があります。ビューホルダーアプローチでは、getItemCount()
、getItemViewType()
、getItemId(position)
およびあらゆる種類のgetItem(position)
メソッドの戻り値を調整することにより、追加のフッターアイテムから保護する必要があります。含めたい。
別のアプローチは、ロードの開始時と終了時にそれぞれProgressBar
の下にFragment
を表示または非表示にすることにより、Activity
またはProgressBar
レベルでRecyclerView
可視性を管理することです。これは、ビューレイアウトにProgressBar
を直接含めるか、カスタムRecyclerView
ViewGroup
クラスに追加することで実現できます。このソリューションは、通常、メンテナンスの削減とバグの削減につながります。
更新:コンテンツの読み込み中にビューを上にスクロールすると、私の提案に問題が生じます。 ProgressBar
は、ビューレイアウトの下部に固定されます。これはおそらくあなたが望む動作ではありません。このため、進行状況ビューホルダーをアダプターに追加することが、おそらく最も優れた機能的なソリューションです。アイテムアクセサメソッドを保護することを忘れないでください。 :)
このソリューションは、このページのAkshar Patelsソリューションに触発されています。少し修正しました。
最初の項目をロードするとき、ProgressBarを中央に配置すると良いように見えます。
ロードするアイテムがなくなったときに下部にある空のパディングが気に入らなかった。このソリューションでは削除されました。
最初のXML:
<Android.support.v7.widget.RecyclerView Android:id="@+id/video_list" Android:paddingBottom="60dp" Android:clipToPadding="false" Android:layout_width="match_parent" Android:layout_height="match_parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> </Android.support.v7.widget.RecyclerView> <ProgressBar Android:id="@+id/progressBar2" style="?android:attr/progressBarStyle" Android:layout_marginTop="10dp" Android:layout_width="wrap_content" Android:layout_centerHorizontal="true" Android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"/>
その後、次のプログラムを追加しました。
最初の結果がロードされたら、これをonScrollListenerに追加します。 ProgressBarを中央から下に移動します。
ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) loadingVideos.getLayoutParams();
layoutParams.topToTop = ConstraintLayout.LayoutParams.UNSET;
loadingVideos.setLayoutParams(layoutParams);
アイテムがなくなったら、次のように下部のパディングを削除します。
recyclerView.setPadding(0,0,0,0);
通常どおりProgressBarを非表示および表示します。
次のように、recycleViewでlayout_aboveタグを使用できます。
<RelativeLayout
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:layout_marginLeft="16dp"
Android:layout_marginRight="16dp"
Android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
Android:id="@+id/rv"
Android:layout_below="@+id/tv2"
Android:layout_width="match_parent"
Android:focusable="false"
Android:layout_height="wrap_content"
Android:layout_marginTop="24dp"
Android:layout_above="@+id/pb_pagination"/>
<ProgressBar
Android:id="@+id/pb_pagination"
style="@style/Widget.AppCompat.ProgressBar"
Android:layout_width="30dp"
Android:layout_height="30dp"
Android:indeterminate="true"
Android:visibility="gone"
Android:layout_alignParentBottom="true"
Android:layout_centerHorizontal="true" />
</RelativeLayout>