Làm cách nào tôi có thể tạo danh sách khi bạn đến cuối danh sách tôi được thông báo để tôi có thể tải thêm các mục?
Làm cách nào tôi có thể tạo danh sách khi bạn đến cuối danh sách tôi được thông báo để tôi có thể tải thêm các mục?
Câu trả lời:
Một giải pháp là thực hiện một OnScrollListener
và thực hiện các thay đổi (như thêm các mục, v.v.) ListAdapter
vào trạng thái thuận tiện trong onScroll
phương thức của nó .
Sau đây ListActivity
hiển thị danh sách các số nguyên, bắt đầu bằng 40, thêm các mục khi người dùng cuộn đến cuối danh sách.
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;
}
}
}
Rõ ràng bạn nên sử dụng các luồng riêng biệt cho các hành động chạy dài (như tải dữ liệu web) và có thể muốn chỉ ra tiến trình trong mục danh sách cuối cùng (như các ứng dụng thị trường hoặc gmail làm).
firstVisible + visibleCount >= totalCount
được đáp ứng nhiều lần với nhiều cuộc gọi đến người nghe. Nếu chức năng tải thêm là một yêu cầu web, (rất có thể là như vậy), hãy thêm một kiểm tra xem có yêu cầu nào đang diễn ra hay không. Mặt khác, hãy kiểm tra xem TotalCount không bằng tổng số trước đó, bởi vì chúng tôi không cần nhiều yêu cầu cho cùng một số mục trong danh sách.
Chỉ muốn đóng góp một giải pháp mà tôi đã sử dụng cho ứng dụng của mình.
Nó cũng dựa trên OnScrollListener
giao diện, nhưng tôi thấy nó có hiệu suất cuộn tốt hơn nhiều trên các thiết bị cấp thấp, vì không có phép tính tổng số có thể nhìn thấy / tổng số nào được thực hiện trong các hoạt động cuộn.
ListFragment
hoặc ListActivity
thực hiệnOnScrollListener
Thêm các phương thức sau vào lớp đó:
@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);
}
}
}
nơi currentPage
là trang của nguồn dữ liệu của bạn mà nên được thêm vào danh sách của bạn, và threshold
là số lượng các mục danh sách (tính từ cuối cùng) mà nên, nếu có thể nhìn thấy, kích hoạt quá trình tải. Ví dụ, nếu bạn đặt threshold
thành 0
, người dùng phải cuộn đến cuối danh sách để tải thêm các mục.
(tùy chọn) Như bạn có thể thấy, "kiểm tra tải thêm" chỉ được gọi khi người dùng dừng cuộn. Để cải thiện khả năng sử dụng, bạn có thể tăng và thêm một chỉ báo tải vào cuối danh sách thông qua listView.addFooterView(yourFooterView)
. Một ví dụ cho chế độ xem chân trang như vậy:
<?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>
(tùy chọn) Cuối cùng, xóa chỉ báo tải đó bằng cách gọi listView.removeFooterView(yourFooterView)
nếu không có thêm mục hoặc trang.
ListFragment
mà không gặp vấn đề gì - chỉ cần làm theo từng bước ở trên và bạn sẽ ổn thôi;) Hoặc bạn có thể cung cấp bất kỳ thông báo lỗi nào không?
getListView().setOnScrollListener(this)
Bạn có thể phát hiện cuối danh sách với sự trợ giúp của onScrollListener , mã làm việc được trình bày bên dưới:
@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();
}
}
Một cách khác để làm điều đó (bên trong bộ chuyển đổi) như sau:
public View getView(int pos, View v, ViewGroup p) {
if(pos==getCount()-1){
addMoreData(); //should be asynctask or thread
}
return view;
}
Xin lưu ý rằng phương thức này sẽ được gọi nhiều lần, vì vậy bạn cần thêm một điều kiện khác để chặn nhiều cuộc gọi của addMoreData()
.
Khi bạn thêm tất cả các thành phần vào danh sách, vui lòng gọi notifyDataSetChanged () bên trong bộ điều hợp của bạn để cập nhật Chế độ xem (nó sẽ được chạy trên luồng UI - runOnUiThread )
getView
. Ví dụ: bạn không được đảm bảo rằng pos
người dùng sẽ xem. Nó có thể chỉ đơn giản là công cụ đo ListView.
Tại Ognyan Bankov GitHub
tôi tìm thấy một giải pháp đơn giản và làm việc!
Nó giúp việc sử dụng Volley HTTP library
làm cho việc kết nối mạng cho các ứng dụng Android trở nên dễ dàng hơn và quan trọng nhất là nhanh hơn. Volley có sẵn thông qua kho AOSP mở.
Các mã đã cho thấy:
Để thống nhất trong tương lai, tôi đã rẽ nhánh repo của Bankov .
Đây là một giải pháp cũng giúp bạn dễ dàng hiển thị chế độ xem tải ở cuối ListView trong khi tải.
Bạn có thể xem các lớp học ở đây:
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/rcper/ListViewWithLoadingIndicatorHelper.java để sử dụng nó các tính năng mà không cần mở rộng từ SimpleListViewWithLoadingTheicator.
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/listener/EndlessScrollListener.java - Trình nghe bắt đầu tải dữ liệu khi người dùng bắt đầu tải dữ liệu sắp chạm đến đáy của ListView.
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/view/SimpleListViewWithLoadingIndicator.java - EndView Bạn có thể sử dụng lớp này trực tiếp hoặc mở rộng từ nó.
Có thể hơi muộn nhưng giải pháp sau đây đã xảy ra rất hữu ích trong trường hợp của tôi. Theo một cách nào đó, tất cả những gì bạn cần làm là thêm vào ListView của bạn Footer
và tạo cho nó addOnLayoutChangeListener
.
http://developer.android.com/reference/android/widget/ListView.html#addFooterView(android.view.View)
Ví dụ:
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");
}
});
Sự kiện này kích hoạt một lần khi một footer trở nên hữu hình và hoạt động như một lá bùa.
Chìa khóa của vấn đề này là phát hiện sự kiện tải thêm, bắt đầu yêu cầu không đồng bộ dữ liệu và sau đó cập nhật danh sách. Ngoài ra một bộ chuyển đổi với chỉ báo tải và trang trí khác là cần thiết. Trong thực tế, vấn đề rất phức tạp trong một số trường hợp góc. Chỉ cần OnScrollListener
thực hiện là không đủ, vì đôi khi các mục không lấp đầy màn hình.
Tôi đã viết một gói cá nhân hỗ trợ danh sách vô tận RecyclerView
và cũng cung cấp triển khai trình tải không đồng bộ AutoPagerFragment
, giúp lấy dữ liệu từ nguồn nhiều trang rất dễ dàng. Nó có thể tải bất kỳ trang nào bạn muốn vào một RecyclerView
sự kiện tùy chỉnh, không chỉ trang tiếp theo.
Đây là địa chỉ: https://github.com/S chếTower / AutoPagerRecyclerManager
Giải pháp tốt nhất cho đến nay mà tôi đã thấy là trong thư viện FastAd CHƯƠNG cho các chế độ xem tái chế. Nó có một EndlessRecyclerOnScrollListener
.
Dưới đây là một ví dụ sử dụng: EndlessScrollListActivity
Khi tôi sử dụng nó cho danh sách cuộn vô tận, tôi đã nhận ra rằng thiết lập là rất mạnh mẽ. Tôi chắc chắn muốn giới thiệu nó.
Tôi đã làm việc trong một giải pháp khác rất giống với giải pháp đó, nhưng, tôi đang sử dụng footerView
để cung cấp khả năng cho người dùng tải xuống nhiều yếu tố hơn khi nhấp vào footerView
, tôi đang sử dụng một "menu" được hiển thị ở trên ListView
và dưới cùng của Chế độ xem chính, "menu" này ẩn phía dưới ListView
, vì vậy, khi listView
cuộn đang cuộn menu biến mất và khi trạng thái cuộn không hoạt động, menu sẽ xuất hiện lại, nhưng khi người dùng cuộn đến cuối listView
, tôi "hỏi" biết nếu footerView
được hiển thị trong trường hợp đó, menu sẽ không xuất hiện và người dùng có thể thấy footerView
để tải thêm nội dung. Đây là mã:
Trân trọng.
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) {
}
});
Tôi biết đó là một câu hỏi cũ và thế giới Android chủ yếu chuyển sang RecyclerViews, nhưng với bất kỳ ai quan tâm, bạn có thể thấy thư viện này rất thú vị.
Nó sử dụng BaseAd CHƯƠNG được sử dụng với ListView để phát hiện khi danh sách đã được cuộn đến mục cuối cùng hoặc khi nó được cuộn ra khỏi mục cuối cùng.
Nó đi kèm với một dự án ví dụ (chỉ có 100 dòng mã Activity) có thể được sử dụng để nhanh chóng hiểu cách thức hoạt động của nó.
Cách sử dụng đơn giản:
class Boy{
private String name;
private double height;
private int age;
//Other code
}
Một bộ chuyển đổi để giữ các đối tượng Boy sẽ trông như sau:
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);
}
Lưu ý cách phương thức getView của BoysAd CHƯƠNG trả về một cuộc gọi đến getView
phương thức của siêu lớp EndlessAd CHƯƠNG . Đây là 100% thiết yếu.
Bây giờ để tạo bộ điều hợp, hãy làm:
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);
}
}
};
Các loadMore
mục là một nút hoặc yếu tố ui khác có thể nhấp vào để lấy dữ liệu hơn từ url. Khi được đặt như được mô tả trong mã, bộ điều hợp biết chính xác khi nào sẽ hiển thị nút đó và khi nào nên tắt nó. Chỉ cần tạo nút trong xml của bạn và đặt nó như hiển thị trong mã bộ điều hợp ở trên.
Thưởng thức.