Listenin sonuna geldiğinizde, daha fazla öğe yükleyebilmem için bildirildiğim bir listeyi nasıl oluşturabilirim?
Listenin sonuna geldiğinizde, daha fazla öğe yükleyebilmem için bildirildiğim bir listeyi nasıl oluşturabilirim?
Yanıtlar:
Bir çözüm, yönteminde uygun bir durumda bir uygulama OnScrollListener
yapmak ve değişiklikler (öğeler ekleme gibi) yapmaktır .ListAdapter
onScroll
Aşağıda ListActivity
, kullanıcı listenin sonuna geldiğinde öğe ekleyerek 40 ile başlayan tam sayıların bir listesi gösterilmektedir.
public class Test extends ListActivity implements OnScrollListener {
Aleph0 adapter = new Aleph0();
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setListAdapter(adapter);
getListView().setOnScrollListener(this);
}
public void onScroll(AbsListView view,
int firstVisible, int visibleCount, int totalCount) {
boolean loadMore = /* maybe add a padding */
firstVisible + visibleCount >= totalCount;
if(loadMore) {
adapter.count += visibleCount; // or any other amount
adapter.notifyDataSetChanged();
}
}
public void onScrollStateChanged(AbsListView v, int s) { }
class Aleph0 extends BaseAdapter {
int count = 40; /* starting amount */
public int getCount() { return count; }
public Object getItem(int pos) { return pos; }
public long getItemId(int pos) { return pos; }
public View getView(int pos, View v, ViewGroup p) {
TextView view = new TextView(Test.this);
view.setText("entry " + pos);
return view;
}
}
}
Açıkça uzun süren eylemler için ayrı web dizileri kullanmanız gerekir (web verilerini yüklemek gibi) ve son liste öğesinde (pazar veya gmail uygulamaları gibi) ilerlemeyi belirtmek isteyebilirsiniz.
firstVisible + visibleCount >= totalCount
dinleyiciye yapılan birden fazla çağrı ile birden çok kez karşılanmasıdır. Daha fazla yükle işlevi bir web isteğiyse (büyük olasılıkla bu olacaktır), bir isteğin devam edip etmediğini kontrol etmek için başka bir kontrol ekleyin. Öte yandan, listedeki aynı sayıda öğe için birden fazla istek gerekmediği için totalCount'un Önceki toplam sayıya eşit olup olmadığını kontrol edin.
Uygulamam için kullandığım bir çözüme katkıda bulunmak istedim.
Ayrıca OnScrollListener
arayüze dayanıyor , ancak kaydırma işlemleri sırasında görünür / toplam sayım hesaplamalarının hiçbiri yapılmadığından, düşük uçlu cihazlarda çok daha iyi bir kaydırma performansına sahip olduğunu buldum.
ListFragment
ya da ListActivity
uygulayınOnScrollListener
Bu sınıfa aşağıdaki yöntemleri ekleyin:
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
//leave this empty
}
@Override
public void onScrollStateChanged(AbsListView listView, int scrollState) {
if (scrollState == SCROLL_STATE_IDLE) {
if (listView.getLastVisiblePosition() >= listView.getCount() - 1 - threshold) {
currentPage++;
//load more list items:
loadElements(currentPage);
}
}
}
nerede currentPage
listenize eklenmelidir sizin veri kaynağı sayfası ve threshold
görünür eğer yükleme sürecini geliştirici olmalıdır (ucundan sayılır) liste öğelerinin sayısıdır. Eğer ayarlarsanız threshold
için 0
, örneğin, kullanıcı daha fazla öğe yüklemek için listenin en sonuna gitmek için vardır.
(isteğe bağlı) Gördüğünüz gibi, "daha fazla yükleme kontrolü" yalnızca kullanıcı kaydırmayı bıraktığında çağrılır. Kullanılabilirliği artırmak için yoluyla listenin sonuna şişirilebilir ve bir yükleme göstergesi ekleyebilirsiniz listView.addFooterView(yourFooterView)
. Bu altbilgi görünümü için bir örnek:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/footer_layout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="10dp" >
<ProgressBar
android:id="@+id/progressBar1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_gravity="center_vertical" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="@+id/progressBar1"
android:padding="5dp"
android:text="@string/loading_text" />
</RelativeLayout>
(isteğe bağlı) Son olarak, listView.removeFooterView(yourFooterView)
başka öğe veya sayfa yoksa arayarak yükleme göstergesini kaldırın .
ListFragment
de herhangi bir sorun olmadan kullanmak - sadece yukarıdaki adımları izleyin ve iyi olacak;) Veya herhangi bir hata mesajı verebilir misiniz?
getListView().setOnScrollListener(this)
Listenin sonunu onScrollListener yardımıyla tespit edebilirsiniz , çalışma kodu aşağıda sunulmuştur:
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (view.getAdapter() != null && ((firstVisibleItem + visibleItemCount) >= totalItemCount) && totalItemCount != mPrevTotalItemCount) {
Log.v(TAG, "onListEnd, extending list");
mPrevTotalItemCount = totalItemCount;
mAdapter.addMoreData();
}
}
Bunu yapmanın başka bir yolu (adaptörün içinde) aşağıdaki gibidir:
public View getView(int pos, View v, ViewGroup p) {
if(pos==getCount()-1){
addMoreData(); //should be asynctask or thread
}
return view;
}
Bu yöntemin birçok kez çağrılacağını unutmayın, bu nedenle birden çok çağrıyı engellemek için başka bir koşul eklemeniz gerekir addMoreData()
.
Listeye tüm öğeleri eklediğinizde , Görünümü güncellemek için lütfen bağdaştırıcınızın içindeki notifyDataSetChanged () öğesini çağırın ( UI iş parçacığında çalıştırılmalıdır - runOnUiThread )
getView
. Örneğin pos
, kullanıcının görüntülediği garanti edilmez . Sadece ListView ölçüm şeyleri olabilir.
At Ognyan Bankov GitHub
ı basit ve çalışma çözüm buldu!
Bu yararlanan Volley HTTP library
Android daha hızlı, en önemlisi daha kolay uygulamaları ve için ağ yapar. Voleybolu açık AOSP deposu aracılığıyla edinilebilir.
Verilen kod şunları gösterir:
Gelecekteki tutarlılık için Bankov'un deposunu çatalladım .
Yükleme sırasında ListView öğesinin sonunda bir yükleme görünümü göstermeyi kolaylaştıran bir çözüm.
Sınıfları burada görebilirsiniz:
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/helper/ListViewWithLoadingIndicatorHelper.java - Kullanmayı mümkün kılmak için yardımcı özellikleri SimpleListViewWithLoadingIndicator genişletmeden.
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/listener/EndlessScrollListener.java - Kullanıcı veri yüklemeye başlayan dinleyici ListView'in altına ulaşmak üzere.
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/view/SimpleListViewWithLoadingIndicator.java - EndlessListView. Bu sınıfı doğrudan kullanabilir veya sınıftan uzatabilirsiniz.
Biraz geç olabilir ama aşağıdaki çözüm benim durumumda çok faydalı oldu. Bir şekilde yapmanız gereken tek şey ListView a'nıza eklemek Footer
ve oluşturmaktır addOnLayoutChangeListener
.
http://developer.android.com/reference/android/widget/ListView.html#addFooterView(android.view.View)
Örneğin:
ListView listView1 = (ListView) v.findViewById(R.id.dialogsList); // Your listView
View loadMoreView = getActivity().getLayoutInflater().inflate(R.layout.list_load_more, null); // Getting your layout of FooterView, which will always be at the bottom of your listview. E.g. you may place on it the ProgressBar or leave it empty-layout.
listView1.addFooterView(loadMoreView); // Adding your View to your listview
...
loadMoreView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
Log.d("Hey!", "Your list has reached bottom");
}
});
Bu etkinlik, bir altbilgi görünür olduğunda bir kez tetiklenir ve bir cazibe gibi çalışır.
Bu sorunun anahtarı, daha fazla yükleme olayını algılamak, veriler için zaman uyumsuzluk isteği başlatmak ve listeyi güncellemektir. Ayrıca yükleme göstergeli bir adaptör ve diğer dekoratörler gereklidir. Aslında, bazı köşe vakalarında sorun çok karmaşıktır. Sadece bir OnScrollListener
uygulama yeterli değildir, çünkü bazen öğeler ekranı doldurmaz.
Sonsuz listeyi destekleyen kişisel bir paket yazdım RecyclerView
ve aynı zamanda AutoPagerFragment
çok sayfalı bir kaynaktan veri almayı çok kolaylaştıran bir asenkron yükleyici uygulaması sağladım . İstediğiniz herhangi bir sayfayı RecyclerView
yalnızca bir sonraki sayfaya değil, özel bir etkinliğe yükleyebilir .
İşte adresi: https://github.com/SphiaTower/AutoPagerRecyclerManager
Şimdiye kadar gördüğüm en iyi çözüm , geri dönüşümcü görünümleri için FastAdapter kütüphanesinde. Bir vardır EndlessRecyclerOnScrollListener
.
İşte bir örnek kullanım: EndlessScrollListActivity
Sonsuz kaydırma listesi için kullandığımda, kurulumun çok sağlam olduğunu fark ettim. Kesinlikle tavsiye ederim.
Ben buna çok benzer başka bir çözüm üzerinde çalışıyorum, ama, ben footerView
kullanıcıya daha fazla öğe indirme imkanı vermek için footerView
kullanıyorum, yukarıda ListView
ve altta gösterilen bir "menü" kullanıyorum üst görünümde, bu "menü" öğesinin altını gizler ListView
, bu nedenle, listView
menü kaydırıldığında kaybolur ve kaydırma durumu boştayken, menü tekrar görünür, ancak kullanıcı sonuna geldiğinde listView
, footerView
bu durumda gösterilip gösterilmediğini bilmek , menü görünmez ve kullanıcı footerView
daha fazla içerik yüklemek için görebilirsiniz . İşte kod:
Saygılarımızla.
listView.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
if(scrollState == SCROLL_STATE_IDLE) {
if(footerView.isShown()) {
bottomView.setVisibility(LinearLayout.INVISIBLE);
} else {
bottomView.setVisibility(LinearLayout.VISIBLE);
} else {
bottomView.setVisibility(LinearLayout.INVISIBLE);
}
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
}
});
Eski bir soru olduğunu biliyorum ve Android dünyası çoğunlukla RecyclerViews'e taşındı, ancak ilgilenen herkes için bu kütüphaneyi çok ilginç bulabilirsiniz .
Listenin son öğeye ne zaman kaydırıldığını veya son öğeden ne zaman kaydırıldığını tespit etmek için ListView ile kullanılan BaseAdapter kullanır.
Nasıl çalıştığını hızlı bir şekilde anlamak için kullanılabilecek örnek bir proje (ancak 100 satırlık Etkinlik kodu) ile birlikte gelir.
Basit kullanım:
class Boy{
private String name;
private double height;
private int age;
//Other code
}
Boy nesnelerini tutmak için bir adaptör şöyle görünecektir:
public class BoysAdapter extends EndlessAdapter<Boy>{
ViewHolder holder = null;
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(parent
.getContext());
holder = new ViewHolder();
convertView = inflater.inflate(
R.layout.list_cell, parent, false);
holder.nameView = convertView.findViewById(R.id.cell);
// minimize the default image.
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Boy boy = getItem(position);
try {
holder.nameView.setText(boy.getName());
///Other data rendering codes.
} catch (Exception e) {
e.printStackTrace();
}
return super.getView(position,convertView,parent);
}
BoysAdapter'ın getView yönteminin EndlessAdapter üst sınıf yöntemine nasıl bir çağrı döndürdüğüne dikkat edin getView
. Bu% 100 zorunludur.
Şimdi bağdaştırıcıyı oluşturmak için şunları yapın:
adapter = new ModelAdapter() {
@Override
public void onScrollToBottom(int bottomIndex, boolean moreItemsCouldBeAvailable) {
if (moreItemsCouldBeAvailable) {
makeYourServerCallForMoreItems();
} else {
if (loadMore.getVisibility() != View.VISIBLE) {
loadMore.setVisibility(View.VISIBLE);
}
}
}
@Override
public void onScrollAwayFromBottom(int currentIndex) {
loadMore.setVisibility(View.GONE);
}
@Override
public void onFinishedLoading(boolean moreItemsReceived) {
if (!moreItemsReceived) {
loadMore.setVisibility(View.VISIBLE);
}
}
};
loadMore
Öğe bir düğme veya url fazla veri almak için tıklandığında olabilecek diğer ui unsurdur. Kodda açıklandığı gibi yerleştirildiğinde, bağdaştırıcı tam olarak bu düğmenin ne zaman gösterileceğini ve ne zaman devre dışı bırakılacağını bilir. Sadece xml'nizde düğmeyi oluşturun ve yukarıdaki adaptör kodunda gösterildiği gibi yerleştirin.
Zevk almak.