我在GridView
回事項目的顯示列表,如果我滾動GridView的整個屏幕不得不Scroll
滾動的GridView不僅GridView
爲此,我用自定義的GridView類ExpandableHeightGridView
。Scroll發生時全屏顯示GridView。我面臨的問題是我已經從WebService API
調用中獲取了值列表,並且我在這個滾動過程中做了一些分頁工作,那是最初它只顯示Ten
GridView中的項目。如果我們向下滾動Grid,它將調用WebService API
調用另一個Ten
值如果響應包含更多的Val它顯示ExpandableHeightGridView
中的所有項目列表,即WebService API
調用正在調用,即使我們不滾動GridView。如果我使用默認的GridView而不是ExpandableHeightGridView
它可以正常工作10,10分頁,但滾動只能用於GridView而不是整個屏幕。我需要兩個task(full screen Scroll,Pagination for 10,10,..etc)
才能執行。
下面是我的代碼 ExpandableHeightGridView.java
public class ExpandableHeightGridView extends GridView {
boolean expanded = true;
public ExpandableHeightGridView(Context context){
super(context);
}
public ExpandableHeightGridView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ExpandableHeightGridView(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
}
public boolean isExpanded() {
return expanded;
}
public void setExpanded(boolean expanded) {
this.expanded = expanded;
}
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// HACK! TAKE THAT ANDROID!
if (isExpanded()) {
// Calculate entire height by providing a very large height hint.
// View.MEASURED_SIZE_MASK represents the largest height possible.
int expandSpec = MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
ViewGroup.LayoutParams params = getLayoutParams();
params.height = getMeasuredHeight();
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
}
Activity類
private void loadFeed(boolean keepListViewShown) {
final FeedRequest<ItemsFeed, ?> request = ItemFeedRequest(0, getLastPostDate());
feedState.lastRequestPageAndSortParams = request.getPageAndSortParams();
getFeedListView().setAdapter(createAdapter(new ArrayList<String>()));
}
private FeedRequest<ItemsFeed, ?> ItemFeedRequest(int page, Date lastPostDate) {
return VisitedItemFeedRequest.builder(this.user.getId())
.pageAndOrdering(PageAndSortParams.builder()
.limit(10).dateOffset(lastPostDate).page(page).build())
.build();
}
private ListAdapter createAdapter(List<String> items) {
PagedAsyncDataLoader<ItemsFeed> pagedDataProvider = new PagedAsyncDataLoader<ItemsFeed>() {
@Override
@SuppressWarnings("unchecked")
public void loadPage(int page, RequestListener<ItemsFeed> requestListener) {
final FeedRequest request =
ItemFeedRequest(page, getLastPostDate());
feedState.lastRequestPageAndSortParams = request.getPageAndSortParams();
//use cache only for the first page of data
long cacheExpirationDelay = page == 0 ? Constants.CacheExpirationDuration.ONE_SECOND :
Constants.CacheExpirationDuration.ALWAYS_EXPIRED;
getRequestController().execute(request, cacheExpirationDelay, requestListener);
}
};
endlessFeedAdapter = new FeedAdapter(createListAdapter(items), pagedDataProvider);
mergeAdapter = new MergeAdapter();
mergeAdapter.addAdapter(endlessFeedAdapter);
return mergeAdapter;
}
}
private final class FeedAdapter extends EndlessFeedAdapter<String,ItemsFeed> {
int count = 0;
public FeedAdapter(ArrayAdapter<String> wrapped, PagedAsyncDataLoader<ItemsFeed>
pagedDataProvider) {
super(wrapped, pagedDataProvider);
}
@Override
protected List<String> collectItems(ItemsFeed FEED) {
return FEED.getData();
}
@Override
protected boolean shouldLoadNextPage(ItemsFeed feed) {
if (feed.getPaging() == null || feed.getPaging().getNext() == null
|| feed.getPaging().getNext().isEmpty())
return false;
return true;
}
@Override
protected void onRequestStarted() {
super.onRequestStarted();
hideErrorLoading();
}
protected void showErrorLoading(String errorMessage) {
getErrorPanelController().showActionButton(android.R.drawable.ic_menu_rotate,
endlessAdapterLoadErrorClickListener)
.errorWithDefaultIcon(errorMessage).show();
}
private final View.OnClickListener endlessAdapterLoadErrorClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
hideErrorLoading();
if (endlessFeedAdapter.getCurrentPage() <= 1) {
reloadData();
} else {
endlessFeedAdapter.restartAppending();
}
}
};
protected void hideErrorLoading() {
getErrorPanelController().hide();
}
private void reloadData() {
feedState.clear();
loadFeed(false);
}
@Override
public void onRequestFailure(Exception spiceException) {
super.onRequestFailure(spiceException);
showErrorLoading(getString(R.string.failed_to_load_feed));
}
@Override
public void onRequestSuccess(ItemsFeed feed, boolean cached) {
super.onRequestSuccess(feed, cached);
feedState.updatePaging(feed.getPaging());
if (cached) {
//ASOC-221 - handle cached result and display message to user that "offline" results were shown
showErrorLoading(getString(R.string.offline_data_displayed));
}
}
@Override
protected void onItemsAdded(List<String> items) {
super.onItemsAdded(items);
feedState.appendItems(items);
}
@Override
protected void onNoMoreData() {
if (feedState.getItems() != null && feedState.getItems().size() > 0) {
//show "No more data" only if current list do not contain any items
//otherwise it is more like "Feed is empty" or "No data" message
mergeAdapter.setActive(noMoreDataView, true);
}
}
}
protected ArrayAdapter<String> createListAdapter(List<String> feed) {
return (new VisitedItemListAdapter(this, feed));//Adapter class to show List Items in Grid
}
EndlessFeedAdapter.java
public abstract class EndlessFeedAdapter<TYPE, RESPONSE> extends EndlessAdapter
implements RequestListener<RESPONSE> {
private PagedAsyncDataLoader<RESPONSE> pagedAsyncDataLoader;
private int currentPage = 1;
private boolean shouldLoadMore = true;
private volatile boolean requestInProgress = false;
public EndlessFeedAdapter(ArrayAdapter<TYPE> wrapped, PagedAsyncDataLoader<RESPONSE>
pagedAsyncDataLoader) {
super(wrapped);
super.setRunInBackground(false);
this.pagedAsyncDataLoader = pagedAsyncDataLoader;
}
@Override
protected boolean cacheInBackground() {
if (shouldLoadMore) {
if (requestInProgress) {
return true;
}
onRequestStarted();
pagedAsyncDataLoader.loadPage(currentPage, this);
return true;
}
return false;
}
protected void onRequestStarted() {
requestInProgress = true;
}
@Override
public void onRequestFailure(Exception spiceException) {
requestInProgress = false;
stopAppending();
}
@Override
public void onRequestSuccess(RESPONSE response, boolean cached) {
//ASOC-221 - it is handled in overriding classes
requestInProgress = false;
++currentPage;
List<TYPE> items = collectItems(response);
if (items == null || items.isEmpty()) {
stopAppending();
onNoMoreData();
return;
}
@SuppressWarnings("unchecked") final ArrayAdapter<TYPE> wrappedAdapter =
((ArrayAdapter<TYPE>)getWrappedAdapter());
List<TYPE> newItems = new ArrayList<>(10);
for (TYPE item : items) {
if (wrappedAdapter.getPosition(item) == -1) {
newItems.add(item);
}
}
if (!newItems.isEmpty()) {
onItemsAdded(newItems);
wrappedAdapter.addAll(newItems);
}
if (!shouldLoadNextPage(response)) {
stopAppending();
onNoMoreData();
}
onDataReady();
}
/**
* Called when adapter has been detected that feed doesn't have more data to load
* it happened inside {@link #onRequestSuccess(Object, boolean)}} if response do not contain any data
* or if call to {@link #shouldLoadNextPage(Object)} returned false
*/
protected void onNoMoreData() {}
/**
* Called when new items have been added to wrapped adapter
* @param items items
*/
protected void onItemsAdded(List<TYPE> items) {}
@Override
protected void appendCachedData() {
}
/**
*
* @param response server response
* @return items returned in response to server request
*/
protected abstract List<TYPE> collectItems(RESPONSE response);
@Override
public void stopAppending() {
this.shouldLoadMore = false;
super.stopAppending();
}
@Override
protected View getPendingView(ViewGroup parent) {
return LayoutInflater.from(parent.getContext()).inflate(R.layout.pending_row, null);
}
@Override
public void setRunInBackground(boolean runInBackground) {
throw new UnsupportedOperationException("EndlessFeedAdapter works only " +
"in runInBackground = false mode");
}
/**
*
* @param response server response
* @return <tt>true</tt> if current response should result in loading of new data page,
* <tt>false</tt> otherwise
*/
protected abstract boolean shouldLoadNextPage(RESPONSE response);
/**
* Make sure that this endless ListView will start loading new data
*/
@Override
public void restartAppending() {
shouldLoadMore = true;
onDataReady();
super.restartAppending();
cacheInBackground();
}
public int getCurrentPage() {
return currentPage;
}
}
PagedAsyncDataLoader.java
public interface PagedAsyncDataLoader<RESULT> {
/**
* Loads page of data asynchronously passing result in provided request listener
* @param page page number (first page is represented by 0)
* @param requestListener request listener
*/
void loadPage(int page,RequestListener<RESULT> requestListener);
}
VisitedItemFeedRequest.java
public class VisitedItemFeedRequest extends FeedRequest<ItemsFeed,ItemApi> {
protected String userId;
protected VisitedItemFeedRequest(Builder builder) {
super(builder);
this.userId = builder.userId;
}
@Override
public ItemsFeed execute(ItemApi itemApi) throws Exception {
PageAndSortParams pageAndSortParams = getPageAndSortParams();
ItemsFeed itemFeed = itemApi.userItemFeed(userId,1,
1,pageAndSortParams.getPage(),10,
pageAndSortParams.getLimit(),true);
return itemFeed;
}
public static Builder builder(String capsuleId){
return new Builder(capsuleId);
}
public static class Builder extends FeedRequest.Builder<VisitedItemFeedRequest> {
private String userId;
public Builder(String capsuleId) {
this.userId = capsuleId;
}
@Override
public VisitedItemFeedRequest build(){
return new VisitedItemFeedRequest(this);
}
}
}
@ nekojsi感謝您的回覆我會檢查並通知您 – Jamal 2014-12-04 10:25:50
我在'ExpandableHeightGridView'中添加了'HeaderGridView' insted,並且在我的xml佈局文件中添加了這個類。我需要澄清一下如何將'ImageView'添加爲'Header' – Jamal 2014-12-04 11:50:03
你可能會使用'HeaderGridView#addHeaderView'方法之一。 – nekojsi 2014-12-04 13:27:34