it-swarm.com.de

Setzen Sie eine unbestimmte Fortschrittsleiste als Fußzeile in ein RecyclerView-Raster

Wie bekomme ich einen unbestimmten Kreisindikator für "Scrollen nach oben, um mehr zu laden" in einem Raster-RecycleView?

Das Muster ist dort beschrieben: http://www.google.com/design/spec/components/progress-activity.html#progress-activity-behavior in "Zweiphasige Ladevorgänge" und "Beispiel 2: Scrollen Laden Sie weitere "Beispielvideos".

Ich versuche dies mit der neuen RecyclerView zu erreichen, aber ich finde keinen "nicht zu hackenden" Weg, dies zu tun, zum einen, weil es keine Möglichkeit gibt, eine Fußzeile hinzuzufügen, die eine vollständige Zeile im Raster abdeckt . Irgendwelche Vorschläge?

50

Das ist sehr einfach.

Die Lösung ist, den gleichen Ansatz der LinearLayoutManager mit einer GridLayoutManager zu verwenden und dann die Methode setSpanSizeLookup für die LayoutManager wie folgt zu verwenden: 

mLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
        @Override
        public int getSpanSize(int position) {
            switch(myAdapter.getItemViewType(position)){
                case MyAdapter.VIEW_TYPES.Product:
                    return 1;
                case MyAdapter.VIEW_TYPES.Progress:
                    return 2; //number of columns of the grid
                default:
                    return -1;
            }
        }
    });

Dadurch wird das Objekt automatisch zu einer vollständigen Zeile des Gitters gemacht (wenn die Zeile nicht vollständig leer ist, geht dieses Element zur nächsten Zeile).

53
Bronx

Beachten Sie, dass die unten stehende Lösung einige potenzielle Probleme und Einschränkungen aufweist. Für eine überarbeitete Lösung überprüfen Sie diese bitteHinzufügen von Elementen zu Endless Scroll RecyclerView mit ProgressBar unten

Hier ist die Lösung, die ich kürzlich gefunden habe: Die Idee ist, RecyclerView mit 2 Arten von Elementen zu haben, eines ist unser übliches Element, das zweite ist die Fortschrittsanzeige, dann müssen wir das Scroll-Ereignis anhören und entscheiden, ob wir mehr laden und die Fortschrittsanzeige anzeigen wollen oder nicht . Also von der Idee zum Beispielcode

progress_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
              Android:orientation="vertical"
              Android:layout_width="match_parent"
              Android:layout_height="match_parent">

    <ProgressBar
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:id="@+id/progressBar"
        Android:indeterminate="true"
        style="@Android:style/Widget.Holo.ProgressBar"
        Android:layout_gravity="center_horizontal"/>
</LinearLayout>

activity_main.xml

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
                xmlns:tools="http://schemas.Android.com/tools"
                xmlns:ring="http://schemas.Android.com/apk/res-auto"
                Android:layout_width="match_parent"
                Android:layout_height="match_parent"
                tools:context=".MainActivity">

    <Android.support.v7.widget.RecyclerView
        Android:id="@+id/my_recycler_view"
        Android:scrollbars="vertical"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"/>
</RelativeLayout>

EndlessRecyclerOnScrollListener.Java

public abstract class EndlessRecyclerOnScrollListener extends RecyclerView.OnScrollListener {
    public static String TAG = EndlessRecyclerOnScrollListener.class.getSimpleName();

    private int previousTotal = 0; // The total number of items in the dataset after the last load
    private boolean loading = true; // True if we are still waiting for the last set of data to load.
    private int visibleThreshold = 1; // The minimum amount of items to have below your current scroll position before loading more.
    int firstVisibleItem, visibleItemCount, totalItemCount;

    private int current_page = 1;

    private LinearLayoutManager mLinearLayoutManager;

    public EndlessRecyclerOnScrollListener(LinearLayoutManager linearLayoutManager) {
        this.mLinearLayoutManager = linearLayoutManager;
    }

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

        visibleItemCount = recyclerView.getChildCount();
        totalItemCount = mLinearLayoutManager.getItemCount();
        firstVisibleItem = mLinearLayoutManager.findFirstVisibleItemPosition();

        if (loading) {
            if (totalItemCount > previousTotal+1) {
                loading = false;
                previousTotal = totalItemCount;
            }
        }
        if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) {
        // End has been reached
        // Do something
            current_page++;
            onLoadMore(current_page);
            loading = true;
        }
    }

    public abstract void onLoadMore(int current_page);
}

MyAdapter.Java

public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private final int VIEW_ITEM = 1;
    private final int VIEW_PROG = 0;

    private List<String> mDataset;

    public static class TextViewHolder extends RecyclerView.ViewHolder {
        public TextView mTextView;
        public TextViewHolder(View v) {
            super(v);
            mTextView = (TextView)v.findViewById(Android.R.id.text1);
        }
    }
    public static class ProgressViewHolder extends RecyclerView.ViewHolder {
        public ProgressBar progressBar;
        public ProgressViewHolder(View v) {
            super(v);
            progressBar = (ProgressBar)v.findViewById(R.id.progressBar);
        }
    }

    public MyAdapter(List<String> myDataset) {
        mDataset = myDataset;
    }

    @Override
    public int getItemViewType(int position) {
        return mDataset.get(position)!=null? VIEW_ITEM: VIEW_PROG;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        RecyclerView.ViewHolder vh;
        if(viewType==VIEW_ITEM) {
            View v = LayoutInflater.from(parent.getContext())
                    .inflate(Android.R.layout.simple_list_item_1, parent, false);

            vh = new TextViewHolder(v);
        }else {
            View v = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.progress_item, parent, false);

            vh = new ProgressViewHolder(v);
        }
        return vh;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if(holder instanceof TextViewHolder){
            ((TextViewHolder)holder).mTextView.setText(mDataset.get(position));
        }else{
            ((ProgressViewHolder)holder).progressBar.setIndeterminate(true);
        }
    }

    @Override
    public int getItemCount() {
        return mDataset.size();
    }
}

und schließlich MainActivity.Java

package virtoos.com.testapps;

import Android.app.Activity;
import Android.os.Bundle;
import Android.os.Handler;
import Android.support.v7.widget.LinearLayoutManager;
import Android.support.v7.widget.RecyclerView;

import Java.util.ArrayList;
import Java.util.List;


public class MainActivity extends Activity {
    private RecyclerView mRecyclerView;
    private LinearLayoutManager mLayoutManager;
    private MyAdapter mAdapter;
    private final List<String> myDataset = new ArrayList<>();
    private Handler handler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        handler = new Handler();
        addItems(20);
        mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);

        // use this setting to improve performance if you know that changes
        // in content do not change the layout size of the RecyclerView
        mRecyclerView.setHasFixedSize(true);

        mLayoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(mLayoutManager);

        mAdapter = new MyAdapter(myDataset);
        mRecyclerView.setAdapter(mAdapter);

        //mRecyclerView.setItemAnimator(new DefaultItemAnimator());

        mRecyclerView.setOnScrollListener(new EndlessRecyclerOnScrollListener(mLayoutManager) {
            @Override
            public void onLoadMore(int current_page) {
                //add progress item
                myDataset.add(null);
                mAdapter.notifyItemInserted(myDataset.size());
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        //remove progress item
                        myDataset.remove(myDataset.size() - 1);
                        mAdapter.notifyItemRemoved(myDataset.size());
                        //add items one by one
                        for (int i = 0; i < 15; i++) {
                            myDataset.add("Item"+(myDataset.size()+1));
                            mAdapter.notifyItemInserted(myDataset.size());
                        }
                        //or you can add all at once but do not forget to call mAdapter.notifyDataSetChanged();
                    }
                }, 2000);
                System.out.println("load");
            }
        });

    }
}
55
Vilen

Hier ist eine kleine Modifikation der @ Vilen Melkumyan-Antwort auf den RecyclerView.Adapter, die für mich besser funktionierte. Sie können Ihre EndlessRecyclerOnScrollListener auf beliebige Weise zum Laden der Daten verwenden und die Fußzeile jederzeit aktivieren oder deaktivieren.

PS: Es hat mit GridLayoutManager gearbeitet.

public class MyRecyclerViewAdapter  extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

private final int VIEW_TYPE_ITEM = 1;
private final int VIEW_TYPE_PROGRESSBAR = 0;
private boolean isFooterEnabled = true;

private List<String> items;

public static class TextViewHolder extends RecyclerView.ViewHolder {
    public TextView mTextView;
    public TextViewHolder(View v) {
        super(v);
        mTextView = (TextView)v.findViewById(Android.R.id.text1);
    }
}
public static class ProgressViewHolder extends RecyclerView.ViewHolder {
    public ProgressBar progressBar;
    public ProgressViewHolder(View v) {
        super(v);
        progressBar = (ProgressBar)v.findViewById(R.id.progressBar);
    }
}

public MyRecyclerViewAdapter(List<String> myDataset) {
    items = myDataset;
}

@Override
public int getItemCount() {
    return  (isFooterEnabled) ? items.size() + 1 : items.size();
}

@Override
public int getItemViewType(int position) {
    return (isFooterEnabled && position >= items.size() ) ? VIEW_TYPE_PROGRESSBAR : VIEW_TYPE_ITEM;
}

/**
 * Enable or disable footer (Default is true)
 *
 * @param isEnabled boolean to turn on or off footer.
 */
public void enableFooter(boolean isEnabled){
    this.isFooterEnabled = isEnabled;
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    RecyclerView.ViewHolder vh;
    if(viewType== VIEW_TYPE_ITEM) {
        View v = LayoutInflater.from(parent.getContext())
                .inflate(Android.R.layout.simple_list_item_1, parent, false);
        vh = new TextViewHolder(v);
    }else {
        View v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.progressbar, parent, false);

        vh = new ProgressViewHolder(v);
    }
    return vh;
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    if(holder instanceof ProgressViewHolder){
        ((ProgressViewHolder)holder).progressBar.setIndeterminate(true);
    } else if(items.size() > 0 && position < items.size()) {
        ((TextViewHolder)holder).mTextView.setText(items.get(position));            
    }
}
}

Meine 2 Cent, Frieden !!

7
cass_

Sehen Sie sich meine Lösung unter https://github.com/ramirodo/endless-recycler-view-adapter Oder https://bintray.com/ramiro/Android/endless-recycler-view- Adapter . Es gibt dort ein Beispiel und auch die Schritte zum Einrichten der Bibliothek in Ihrem Projekt.

Sie müssen lediglich den Recycler-Ansichtsadapter um die erforderlichen Methoden erweitern. Sie können auch das Layout der Fortschrittsfußzeile einrichten.

1
Ramiro

Sie können die Antwort von Bronx vereinfachen, indem Sie den Code in einen Adapter einfügen.

public class ArticleGridAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private final int VIEW_ITEM = 0;
    private final int VIEW_LOADING = 1;

    private Context mContext;
    private List<Article> mArticles = new ArrayList<>();
    private RecyclerView mRecyclerView;
    private GridLayoutManager mManager;

    public ArticleGridAdapter(Context context, List<Article> articles, RecyclerView recyclerView) {
        this.mContext = context;
        this.mArticles = articles;
        this.mRecyclerView = recyclerView;
        this.mManager = (GridLayoutManager) recyclerView.getLayoutManager();

        mManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
            @Override
            public int getSpanSize(int position) {
                return getItemViewType(position) == VIEW_LOADING ? mManager.getSpanCount() : 1;
            }
        });
    }
}
0
wonsuc