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 OnScrollListeneryapmak ve değişiklikler (öğeler ekleme gibi) yapmaktır .ListAdapteronScroll
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 >= totalCountdinleyiciye 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 OnScrollListenerarayü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.
ListFragmentya da ListActivityuygulayınOnScrollListenerBu 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 currentPagelistenize eklenmelidir sizin veri kaynağı sayfası ve thresholdgö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 thresholdiç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 .
ListFragmentde 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 libraryAndroid 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 Footerve 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 OnScrollListeneruygulama yeterli değildir, çünkü bazen öğeler ekranı doldurmaz.
Sonsuz listeyi destekleyen kişisel bir paket yazdım RecyclerViewve 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ı RecyclerViewyalnı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 footerViewkullanıcıya daha fazla öğe indirme imkanı vermek için footerViewkullanıyorum, yukarıda ListViewve altta gösterilen bir "menü" kullanıyorum üst görünümde, bu "menü" öğesinin altını gizler ListView, bu nedenle, listViewmenü kaydırıldığında kaybolur ve kaydırma durumu boştayken, menü tekrar görünür, ancak kullanıcı sonuna geldiğinde listView, footerViewbu durumda gösterilip gösterilmediğini bilmek , menü görünmez ve kullanıcı footerViewdaha 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.