SectionListView.java
/*
* Copyright (C) 2003-2014 eXo Platform SAS.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 3 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.exoplatform.widget;
import java.security.InvalidParameterException;
import org.exoplatform.ui.social.ActivityStreamFragment;
import org.exoplatform.utils.ExoConstants;
import android.content.Context;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewParent;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.FrameLayout;
import android.widget.HeaderViewListAdapter;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
/**
* View displaying the list with sectioned header.
*/
public class SectionListView extends ListView implements OnScrollListener {
/**
* The view that contains the fixed section header
*/
private View transparentView;
/**
* The Fragment that holds this list view
*/
private ActivityStreamFragment parentFragment;
/**
* The progress bar in the footer
*/
private ProgressBar autoLoadProgress;
/**
* A flag that indicates whether the user has scrolled to reach the current position in the list
*/
private boolean hasScrolled;
public SectionListView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
commonInitialisation();
}
public SectionListView(final Context context, final AttributeSet attrs) {
super(context, attrs);
commonInitialisation();
}
public SectionListView(final Context context) {
super(context);
commonInitialisation();
}
protected final void commonInitialisation() {
setOnScrollListener(this);
setVerticalFadingEdgeEnabled(false);
setFadingEdgeLength(0);
autoLoadProgress = new ProgressBar(getContext(), null, android.R.attr.progressBarStyleSmall);
autoLoadProgress.setLayoutParams(new ListView.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
autoLoadProgress.setPadding(0, 0, 0, 10); // 0px left, top and right, 10px bottom
autoLoadProgress.setVisibility(View.INVISIBLE);
LinearLayout layout = new LinearLayout(getContext());
layout.setGravity(Gravity.CENTER);
layout.addView(autoLoadProgress);
addFooterView(layout);
hasScrolled = false;
}
@Override
public void setAdapter(final ListAdapter adapter) {
if (!(adapter instanceof SectionListAdapter)) {
throw new IllegalArgumentException("The adapter needds to be of type "
+ SectionListAdapter.class + " and is " + adapter.getClass());
}
super.setAdapter(adapter);
final ViewParent parent = getParent();
if (!(parent instanceof FrameLayout)) {
throw new IllegalStateException("Section List should have FrameLayout as parent!");
}
if (transparentView != null) {
((FrameLayout) parent).removeView(transparentView);
}
transparentView = ((SectionListAdapter) adapter).getTransparentSectionView();
final FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT);
((FrameLayout) parent).addView(transparentView, lp);
if (adapter.isEmpty()) {
transparentView.setVisibility(View.INVISIBLE);
}
}
public void setParentFragment(ActivityStreamFragment p) {
if (p != null) {
parentFragment = p;
} else {
throw new InvalidParameterException("You must set a proper Fragment object.");
}
}
@Override
public void onScroll(final AbsListView view,
final int firstVisibleItem,
final int visibleItemCount,
final int totalItemCount) {
ListAdapter a = getAdapter();
SectionListAdapter adapter = null;
if (a instanceof HeaderViewListAdapter)
adapter = (SectionListAdapter)((HeaderViewListAdapter) a).getWrappedAdapter();
else
adapter = (SectionListAdapter) getAdapter();
if (adapter != null) {
adapter.makeSectionInvisibleIfFirstInList(firstVisibleItem);
}
// More activities will be automatically loaded if:
// - the user has scrolled AND
// - the user has reached the bottom of the list
if (hasScrolled && totalItemCount > 0 && firstVisibleItem+visibleItemCount==totalItemCount) {
autoLoadProgress.setVisibility(View.VISIBLE);
parentFragment.onLoadMore(ExoConstants.NUMBER_OF_ACTIVITY, totalItemCount-1, firstVisibleItem);
// set back to false to avoid multiple calls to the onLoadMore(...) method
hasScrolled = false;
}
}
public ProgressBar getAutoLoadProgressBar() {
return autoLoadProgress;
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// false if the user is not scrolling, true otherwise
hasScrolled = (scrollState!=OnScrollListener.SCROLL_STATE_IDLE);
}
}