더 많은 항목을로드 할 수 있도록 목록 끝에 도달했을 때 목록을 작성하려면 어떻게해야합니까?
더 많은 항목을로드 할 수 있도록 목록 끝에 도달했을 때 목록을 작성하려면 어떻게해야합니까?
답변:
한 가지 해결책은 구현 시 편리한 방법으로 OnScrollListener
항목 추가 등 을 구현하고 변경 ListAdapter
하는 onScroll
것입니다.
다음 ListActivity
은 40부터 시작하여 사용자가 목록의 끝으로 스크롤 할 때 항목을 추가하는 정수 목록을 보여줍니다.
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;
}
}
}
웹 데이터로드와 같은 장기 실행 작업에는 별도의 스레드를 사용해야하며 마지막 목록 항목의 진행률 (예 : 마켓 또는 gmail 앱)을 표시 할 수 있습니다.
firstVisible + visibleCount >= totalCount
은 리스너를 여러 번 호출 하여 조건 이 여러 번 충족 된다는 것 입니다. 추가 기능이 웹 요청 인 경우 (아마도 가능할 것임) 요청이 진행 중인지 다른 확인을 추가하십시오. 반면에 totalCount가 Previous total count와 같지 않은지 확인하십시오. 목록에서 같은 수의 항목에 대해 여러 요청이 필요하지 않기 때문입니다.
내 앱에 사용한 솔루션을 제공하고 싶었습니다.
또한 OnScrollListener
인터페이스를 기반으로 하지만 스크롤 작업 중에 가시 / 총 카운트 계산이 수행되지 않으므로 로우 엔드 장치에서 스크롤 성능이 훨씬 뛰어납니다.
ListFragment
또는 ListActivity
구현 하자OnScrollListener
해당 클래스에 다음 메소드를 추가하십시오.
@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);
}
}
}
where currentPage
는 목록에 추가해야하는 데이터 소스의 페이지이며 threshold
, 표시되는 경우로드 프로세스를 트리거해야하는 목록 항목 (끝부터 계산)의 수입니다. 예를 들어로 설정 threshold
하면 0
더 많은 항목을로드하기 위해 사용자가 목록의 맨 끝으로 스크롤해야합니다.
(선택 사항) 보시다시피 "로드 추가 검사"는 사용자가 스크롤을 멈출 때만 호출됩니다. 사용성을 향상시키기 위해을 통해로드 표시기를 팽창시키고 목록 끝에 추가 할 수 있습니다 listView.addFooterView(yourFooterView)
. 바닥 글보기의 한 가지 예 :
<?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>
(선택 사항) 마지막으로 listView.removeFooterView(yourFooterView)
더 이상 항목이나 페이지가없는 경우 호출하여로드 표시기를 제거하십시오 .
ListFragment
문제없이 함께 사용합니다 -위의 각 단계를 따르십시오. 그러면 괜찮을 것입니다.) 또는 오류 메시지를 제공 할 수 있습니까?
getListView().setOnScrollListener(this)
onScrollListener의 도움으로 목록의 끝을 감지 할 수 있습니다 . 작업 코드는 다음과 같습니다.
@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();
}
}
이를 수행하는 다른 방법 (어댑터 내부)은 다음과 같습니다.
public View getView(int pos, View v, ViewGroup p) {
if(pos==getCount()-1){
addMoreData(); //should be asynctask or thread
}
return view;
}
이 메소드는 여러 번 호출되므로 여러 호출을 차단하려면 다른 조건을 추가해야합니다 addMoreData()
.
목록에 모든 요소를 추가 할 때 어댑터 내부의 notifyDataSetChanged () 를 호출 하여보기를 업데이트하십시오 (UI 스레드에서 실행되어야 함 -runOnUiThread )
getView
. 예를 들어, 사용자 pos
가 볼 수 있다고 보장되지는 않습니다 . 단순히 ListView 측정 항목 일 수 있습니다.
에서 Ognyan Bankov GitHub
나는 간단하고 작동 해결책을 발견!
그것은 Volley HTTP library
안드로이드 앱을위한 네트워킹을 더 쉽고 가장 중요하게, 더 빠르게 만드는 것을 사용합니다. 발리는 오픈 AOSP 리포지토리를 통해 사용할 수 있습니다.
주어진 코드는 다음을 보여줍니다.
미래의 일관성을 위해 나는 Bankov의 repo를 포크했다 .
다음은로드하는 동안 ListView의 끝에로드보기를 쉽게 표시 할 수있는 솔루션입니다.
여기에서 수업을 볼 수 있습니다.
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/helper/ListViewWithLoadingIndicatorHelper.java- 사용할 수 있도록 돕는 도우미 SimpleListViewWithLoadingIndicator에서 확장하지 않고 기능.
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/listener/EndlessScrollListener.java- 사용자가 데이터로드를 시작할 때 리스너 ListView의 맨 아래에 도달하려고합니다.
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/view/SimpleListViewWithLoadingIndicator.java-EndlessListView . 이 클래스를 직접 사용하거나 확장 할 수 있습니다.
조금 늦을 수도 있지만 다음과 같은 해결책이 제 경우에는 매우 유용했습니다. 당신이해야 할 방법은 ListView에 추가하고 Footer
그것을 만드는 것 addOnLayoutChangeListener
입니다.
http://developer.android.com/reference/android/widget/ListView.html#addFooterView(android.view.View)
예를 들면 다음과 같습니다.
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");
}
});
바닥 글이 표시되고 매력처럼 작동하면이 이벤트가 한 번 발생합니다.
이 문제의 핵심은 더 많은 이벤트를 감지하고 데이터에 대한 비동기 요청을 시작한 다음 목록을 업데이트하는 것입니다. 또한 로딩 표시기와 다른 데코레이터가있는 어댑터가 필요합니다. 실제로 일부 경우에는 문제가 매우 복잡합니다. 그냥 OnScrollListener
가끔 항목이 화면을 채울하지 않기 때문에 구현은 충분하지 않습니다.
에 대한 끝없는 목록을 지원하는 개인 패키지를 작성했으며 여러 페이지 소스에서 데이터를 매우 쉽게 가져올 RecyclerView
수있는 비동기 로더 구현 AutoPagerFragment
을 제공합니다 . RecyclerView
다음 페이지뿐만 아니라 사용자 정의 이벤트에 원하는 페이지를로드 할 수 있습니다 .
주소는 다음과 같습니다. https://github.com/SphiaTower/AutoPagerRecyclerManager
지금까지 내가 본 최고의 솔루션은 FastAdapter 라이브러리에 재활용 뷰가 있습니다. 이 있습니다 EndlessRecyclerOnScrollListener
.
사용 예는 다음과 같습니다. EndlessScrollListActivity
끝없는 스크롤 목록에 사용하면 설정이 매우 강력하다는 것을 알았습니다. 나는 그것을 추천합니다.
나는 그것과 매우 비슷한 다른 솔루션에서 일하고 있지만,를 사용 footerView
하여 사용자가을 클릭하여 더 많은 요소를 다운로드 할 수있는 가능성을 제공하고 있습니다 footerView
. 나는 "메뉴"를 사용하고 있습니다 ListView
. 상위보기에서이 "메뉴"는의 하단을 숨기 ListView
므로 listView
메뉴를 스크롤 할 때 메뉴가 사라지고 스크롤 상태가 유휴 상태 일 때 메뉴가 다시 나타나지만 사용자가의 끝으로 스크롤하면 listView
"요청" 이 경우 footerView
메뉴가 표시되면 메뉴가 표시되지 않고 footerView
더 많은 콘텐츠를로드 할 수 있습니다. 여기 코드가 있습니다 :
문안 인사.
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) {
}
});
나는 오래된 질문을 알고 있으며 안드로이드 세계는 주로 RecyclerViews로 옮겨 갔지만 관심있는 사람이라면 이 라이브러리가 매우 흥미로울 것입니다.
ListView와 함께 사용되는 BaseAdapter를 사용하여 목록이 마지막 항목으로 스크롤 된시기 또는 마지막 항목에서 멀리 스크롤되는시기를 감지합니다.
작동 방식을 빠르게 이해하는 데 사용할 수있는 예제 프로젝트 (거의 100 줄의 활동 코드)가 제공됩니다.
간단한 사용법 :
class Boy{
private String name;
private double height;
private int age;
//Other code
}
Boy 오브젝트를 보유하는 어댑터는 다음과 같습니다.
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의 getView 메소드가 EndlessAdapter 수퍼 클래스의 getView
메소드에 대한 호출을 리턴하는 방법에 주목하십시오 . 100 % 필수입니다.
이제 어댑터를 작성하려면 다음을 수행하십시오.
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
항목은 버튼이나 URL에서 더 많은 데이터를 가져 오기 위해 클릭 할 수있는 다른 UI 요소입니다. 코드에 설명 된대로 배치하면 어댑터는 해당 단추를 표시 할시기와 비활성화 할시기를 정확하게 알고 있습니다. xml에서 버튼을 만들고 위의 어댑터 코드에 표시된 것처럼 배치하십시오.
즐겨.