Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/208.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 使用ProgressBar进行分页的无限循环视图_Android_Android Listview_Android Recyclerview_Android 5.0 Lollipop_Android Progressbar - Fatal编程技术网

Android 使用ProgressBar进行分页的无限循环视图

Android 使用ProgressBar进行分页的无限循环视图,android,android-listview,android-recyclerview,android-5.0-lollipop,android-progressbar,Android,Android Listview,Android Recyclerview,Android 5.0 Lollipop,Android Progressbar,我正在使用一个API,从API中一批十个地获取对象。对于分页,我使用 一切正常。现在剩下的就是在API获取下一批对象时,在列表底部添加一个进度微调器。这是谷歌Play商店应用程序的屏幕截图,显示了一个ProgressBar,当然是一个RecyclerView: 问题是,无论是RecyclerView还是EndlesRecycleronScrollListener都没有内置支持,在获取下一批对象时,在底部显示ProgressBar 我已经看到了以下答案: 1. 2. 我对这些答案不满意(都是同一

我正在使用一个API,从API中一批十个地获取对象。对于分页,我使用

一切正常。现在剩下的就是在API获取下一批对象时,在列表底部添加一个进度微调器。这是谷歌Play商店应用程序的屏幕截图,显示了一个
ProgressBar
,当然是一个
RecyclerView

问题是,无论是
RecyclerView
还是
EndlesRecycleronScrollListener
都没有内置支持,在获取下一批对象时,在底部显示
ProgressBar

我已经看到了以下答案:

1.

2.

我对这些答案不满意(都是同一个人的)。这包括在用户滚动时将
null
对象插入数据集中,然后在下一批交付后将其取出。它看起来像是一个回避了主要问题的黑客,这些问题可能会正常工作,也可能不会正常工作。它会在列表中引起一些不和谐和失真

在这里,使用并不是一个解决方案
SwipeRefreshLayout
涉及从顶部提取最新项目,并且它不会显示进度视图

有人能提供一个很好的解决方案吗?我很想知道谷歌是如何为他们自己的应用程序实现这一点的(Gmail应用程序也有)。有没有详细说明这一点的文章?所有答案和意见将不胜感激。多谢各位

一些其他参考资料

1.。(概述…)

2.。(更多相同的…)


3.我在我的旧项目上实现了这一点,我做了如下

我已经创建了一个
界面
,就像你的例子中的那些家伙所做的那样

public interface LoadMoreItems {
  void LoadItems();
}
然后我在我的
适配器上添加了一个
addOnScrollListener()

 recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(RecyclerView recyclerView,
                                   int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);

                totalItemCount = linearLayoutManager.getItemCount();
                lastVisibleItem = linearLayoutManager
                        .findLastVisibleItemPosition();
                if (!loading
                        && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
                    //End of the items
                    if (onLoadMoreListener != null) {
                        onLoadMoreListener.LoadItems();
                    }
                    loading = true;

                }
            }
        });
在我的
main活动
中,我放置
LoadItems()
以添加其他项目的位置是:

mAdapter.setOnLoadMoreListener(new LoadMoreItems() {
        @Override
        public void LoadItems() {
            DataItemsList.add(null);
            mAdapter.notifyItemInserted(DataItemsList.size() - 1);

            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    //   remove progress item
                    DataItemsList.remove(DataItemsList.size() - 1);
                    mAdapter.notifyItemRemoved(DataItemsList.size());
                    //add items one by one
                    //When you've added the items call the setLoaded()
                    mAdapter.setLoaded();
                    //if you put all of the items at once call
                    // mAdapter.notifyDataSetChanged();
                }
            }, 2000); //time 2 seconds

        }
    });
关于更多信息,我只是遵循了这个(注意:这是使用
AsyncTask
作为我的答案可能很有用,因为我不是用
API
中的数据手动完成的,但它也应该可以工作),这篇文章对我也很有帮助

我也不知道你是否给它起了名字,但我也找到了这篇文章,也许它也能帮助你

如果这不是你要找的,让我知道,告诉我这段代码有什么问题,我会尝试修改它作为你喜欢的

希望能有帮助

编辑 因为您不想删除项目。。。我发现我猜有个人只删除了这篇文章的
页脚:

这是针对
ListView
的,但我知道您可以将其调整为
RecyclerView
他没有删除任何项目,他只是将
可见/不可见的
进度条
看一看:


另外请注意:这个问题还有另一种方法

  • 首先,适配器的getItemCount返回
    listItems.size()+1

  • getItemViewType()
    中为
    position>=listItems.size()返回
    VIEW\u TYPE\u加载
    。这样,加载器将仅显示在回收器视图列表的末尾。此解决方案的唯一问题是,即使在到达最后一页后,也会显示加载程序,因此为了修复此问题,您将
    x-pagination-total-count
    存储在适配器中,并且

  • 然后将条件更改为将视图类型返回到


    (position>=listItem.size())&&&(listItem.size我喜欢在适配器中添加进度视图持有者的想法,但这往往会导致一些丑陋的逻辑操作,以获得所需的内容。视图持有者方法通过调整
    getItemCount()的返回值,迫使您防止额外的页脚项
    getItemViewType()
    getItemId(position)
    以及您可能希望包括的任何类型的
    getItem(position)
    方法

    另一种方法是管理
    ProgressBar
    Fragment
    Activity
    级别的可见性,方法是在加载开始和结束时分别在
    RecyclerView
    下方显示或隐藏
    ProgressBar
    。这可以通过将
    ProgressBar
    直接包含在v查看布局或将其添加到自定义的
    RecyclerView
    ViewGroup
    类。此解决方案通常会减少维护和错误


    更新:我的建议会在加载内容时将视图卷回时产生问题。
    ProgressBar
    将粘贴到视图布局的底部。这可能不是您想要的行为。因此,向适配器添加进度视图支架可能是最好的功能解决方案。请不要忘记保护您的项目访问器方法。:)

    不同的方法是在onBindViewHolder中启动API调用,并将其初始放置到项目视图中以查看一些进度指示器。调用完成后,更新视图(隐藏进度并显示收到的数据)。例如,对于用于图像加载的毕加索,onBindViewHolder方法如下所示

    @Override
    public void onBindViewHolder(final MovieViewHolder holder, final int position) {
        final Movie movie = items.get(position);
        holder.imageProgress.setVisibility(View.VISIBLE);
        Picasso.with(context)
                .load(NetworkingUtils.getMovieImageUrl(movie.getPosterPath()))
                .into(holder.movieThumbImage, new Callback() {
                    @Override
                    public void onSuccess() {
                        holder.imageProgress.setVisibility(View.GONE);
                    }
                    @Override
                    public void onError() {
    
                    }
                });
    }
    
    在我看来,可能出现两种情况:

  • 您只需一次呼叫即可下载light版本中的所有项目(例如,适配器立即知道他需要处理40张图片,但按需下载->案例,我之前在毕加索那里展示过)
  • 您正在处理真正的延迟加载,并要求服务器为您提供额外的数据块。在这种情况下,第一个先决条件是服务器提供足够的响应和必要的信息。前例 { “偏移量”:0, “总数”:100, “项目”:[{items}] }
  • 那里
    @Override
    public void onBindViewHolder(final MovieViewHolder holder, final int position) {
        final Movie movie = items.get(position);
        holder.imageProgress.setVisibility(View.VISIBLE);
        Picasso.with(context)
                .load(NetworkingUtils.getMovieImageUrl(movie.getPosterPath()))
                .into(holder.movieThumbImage, new Callback() {
                    @Override
                    public void onSuccess() {
                        holder.imageProgress.setVisibility(View.GONE);
                    }
                    @Override
                    public void onError() {
    
                    }
                });
    }
    
    public class ForecastListAdapter extends RecyclerView.Adapter<ForecastListAdapter.ForecastVH> {
    private final Context context;
    private List<Forecast> items;
    private ILazyLoading lazyLoadingListener;
    
    public static final int VIEW_TYPE_FIRST         = 0;
    public static final int VIEW_TYPE_REST          = 1;
    public static final int VIEW_TYPE_PROGRESS      = 2;
    
    public static final int totalItemsCount = 14;
    
    public ForecastListAdapter(List<Forecast> items, Context context, ILazyLoading lazyLoadingListener) {
        this.items = items;
        this.context = context;
        this.lazyLoadingListener = lazyLoadingListener;
    }
    
    public void addItems(List<Forecast> additionalItems){
        this.items.addAll(additionalItems);
        notifyDataSetChanged();
    }
    
    @Override
    public int getItemViewType(int position) {
        if(totalItemsCount > items.size() && position == items.size()){
            return VIEW_TYPE_PROGRESS;
        }
        switch (position){
            case VIEW_TYPE_FIRST:
                return VIEW_TYPE_FIRST;
            default:
                return VIEW_TYPE_REST;
        }
    }
    
    @Override
    public ForecastVH onCreateViewHolder(ViewGroup parent, int viewType) {
        View v;
        switch (viewType){
            case VIEW_TYPE_PROGRESS:
                v = LayoutInflater.from(parent.getContext()).inflate(R.layout.forecast_list_item_progress, parent, false);
                if (lazyLoadingListener != null) {
                    lazyLoadingListener.getAdditionalItems();
                }
                break;
            case VIEW_TYPE_FIRST:
                v = LayoutInflater.from(parent.getContext()).inflate(R.layout.forecast_list_item_first, parent, false);
                break;
            default:
                v = LayoutInflater.from(parent.getContext()).inflate(R.layout.forecast_list_item_rest, parent, false);
                break;
        }
        return new ForecastVH(v);
    }
    
    @Override
    public void onBindViewHolder(ForecastVH holder, int position) {
        if(position < items.size()){
            Forecast item = items.get(position);
            holder.date.setText(FormattingUtils.formatTimeStamp(item.getDt()));
            holder.minTemperature.setText(FormattingUtils.getRoundedTemperature(item.getTemp().getMin()));
            holder.maxTemperature.setText(FormattingUtils.getRoundedTemperature(item.getTemp().getMax()));
        }
    
    }
    
    @Override
    public long getItemId(int position) {
        long i = super.getItemId(position);
        return i;
    }
    
    @Override
    public int getItemCount() {
        if (items == null) {
            return 0;
        }
        if(items.size() < totalItemsCount){
            return items.size() + 1;
        }else{
            return items.size();
        }
    }
    
    public class ForecastVH extends RecyclerView.ViewHolder{
        @BindView(R.id.forecast_date)TextView date;
        @BindView(R.id.min_temperature)TextView minTemperature;
        @BindView(R.id.max_temperature) TextView maxTemperature;
        public ForecastVH(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
        }
    }
    
    public interface ILazyLoading{
        public void getAdditionalItems();
    }}
    
        <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" />
    
    progressBar = findViewById(R.id.progressBar);
    
    void showProgressView() {
        progressBar.setVisibility(View.VISIBLE);
    }
    
    void hideProgressView() {
        progressBar.setVisibility(View.INVISIBLE);
    }
    
    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
    }
    
    <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"/>
    
    ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) loadingVideos.getLayoutParams();
    layoutParams.topToTop = ConstraintLayout.LayoutParams.UNSET;
    loadingVideos.setLayoutParams(layoutParams);
    
    recyclerView.setPadding(0,0,0,0);
    
    <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>
    
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerview_cities"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@id/preogressbar"
        />
    <ProgressBar
        android:id="@+id/preogressbar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="gone"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        />
    </RelativeLayout>
    
     public void insert(int position, JobModel data) {
                 joblist.add(position, data);
                 notifyItemInserted(position);
            }.
        
      public void updateList(  ArrayList<JobModel> data) {
            try {
                for (int i = joblist.size(); i < data.size(); i++)
                    insert(i, data.get(i));   
          }catch (Exception e){} }.
    
     val concatAdapter = ConcatAdapter(dataAdapter, progressAdapter)