automatically load new headlines when scrolled to the bottom
This commit is contained in:
parent
918235592a
commit
24e092d190
33
res/layout/headlines_row_loadmore.xml
Normal file
33
res/layout/headlines_row_loadmore.xml
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/headlines_row_loadmore"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?headlineNormalBackground"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal" >
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/loadmore_content"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:padding="10dp" >
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/loadmore_progress"
|
||||||
|
style="?android:attr/progressBarStyleSmall"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:paddingLeft="6dp"
|
||||||
|
android:id="@+id/loadmore_label"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Loading, please wait..." />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -24,6 +24,13 @@ public class Article implements Parcelable {
|
|||||||
readFromParcel(in);
|
readFromParcel(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Article(int id) {
|
||||||
|
this.id = id;
|
||||||
|
this.title = "";
|
||||||
|
this.link = "";
|
||||||
|
this.tags = new ArrayList<String>();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int describeContents() {
|
public int describeContents() {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -23,6 +23,8 @@ import android.view.View;
|
|||||||
import android.view.ContextMenu.ContextMenuInfo;
|
import android.view.ContextMenu.ContextMenuInfo;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.AbsListView;
|
||||||
|
import android.widget.AbsListView.OnScrollListener;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.AdapterView.AdapterContextMenuInfo;
|
import android.widget.AdapterView.AdapterContextMenuInfo;
|
||||||
import android.widget.AdapterView.OnItemClickListener;
|
import android.widget.AdapterView.OnItemClickListener;
|
||||||
@ -37,13 +39,18 @@ import com.google.gson.JsonArray;
|
|||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
|
||||||
public class HeadlinesFragment extends Fragment implements OnItemClickListener {
|
public class HeadlinesFragment extends Fragment implements OnItemClickListener, OnScrollListener {
|
||||||
public static enum ArticlesSelection { ALL, NONE, UNREAD };
|
public static enum ArticlesSelection { ALL, NONE, UNREAD };
|
||||||
|
|
||||||
|
public static final int HEADLINES_REQUEST_SIZE = 30;
|
||||||
|
public static final int HEADLINES_BUFFER_MAX = 500;
|
||||||
|
|
||||||
private final String TAG = this.getClass().getSimpleName();
|
private final String TAG = this.getClass().getSimpleName();
|
||||||
|
|
||||||
private Feed m_feed;
|
private Feed m_feed;
|
||||||
private int m_activeArticleId;
|
private int m_activeArticleId;
|
||||||
|
private boolean m_refreshInProgress = false;
|
||||||
|
private boolean m_canLoadMore = false;
|
||||||
|
|
||||||
private ArticleListAdapter m_adapter;
|
private ArticleListAdapter m_adapter;
|
||||||
private ArticleList m_articles = new ArticleList();
|
private ArticleList m_articles = new ArticleList();
|
||||||
@ -81,6 +88,7 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener {
|
|||||||
m_articles = savedInstanceState.getParcelable("articles");
|
m_articles = savedInstanceState.getParcelable("articles");
|
||||||
m_activeArticleId = savedInstanceState.getInt("activeArticleId");
|
m_activeArticleId = savedInstanceState.getInt("activeArticleId");
|
||||||
m_selectedArticles = savedInstanceState.getParcelable("selectedArticles");
|
m_selectedArticles = savedInstanceState.getParcelable("selectedArticles");
|
||||||
|
m_canLoadMore = savedInstanceState.getBoolean("canLoadMore");
|
||||||
}
|
}
|
||||||
|
|
||||||
View view = inflater.inflate(R.layout.headlines_fragment, container, false);
|
View view = inflater.inflate(R.layout.headlines_fragment, container, false);
|
||||||
@ -89,6 +97,7 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener {
|
|||||||
m_adapter = new ArticleListAdapter(getActivity(), R.layout.headlines_row, (ArrayList<Article>)m_articles);
|
m_adapter = new ArticleListAdapter(getActivity(), R.layout.headlines_row, (ArrayList<Article>)m_articles);
|
||||||
list.setAdapter(m_adapter);
|
list.setAdapter(m_adapter);
|
||||||
list.setOnItemClickListener(this);
|
list.setOnItemClickListener(this);
|
||||||
|
list.setOnScrollListener(this);
|
||||||
registerForContextMenu(list);
|
registerForContextMenu(list);
|
||||||
|
|
||||||
Log.d(TAG, "onCreateView, feed=" + m_feed);
|
Log.d(TAG, "onCreateView, feed=" + m_feed);
|
||||||
@ -114,15 +123,19 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener {
|
|||||||
|
|
||||||
if (list != null) {
|
if (list != null) {
|
||||||
Article article = (Article)list.getItemAtPosition(position);
|
Article article = (Article)list.getItemAtPosition(position);
|
||||||
m_articleOps.openArticle(article, 0);
|
if (article.id >= 0) {
|
||||||
|
m_articleOps.openArticle(article, 0);
|
||||||
|
|
||||||
m_activeArticleId = article.id;
|
m_activeArticleId = article.id;
|
||||||
m_adapter.notifyDataSetChanged();
|
m_adapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked", "serial" })
|
@SuppressWarnings({ "unchecked", "serial" })
|
||||||
public void refresh(boolean append) {
|
public void refresh(boolean append) {
|
||||||
|
m_refreshInProgress = true;
|
||||||
|
|
||||||
HeadlinesRequest req = new HeadlinesRequest(getActivity().getApplicationContext());
|
HeadlinesRequest req = new HeadlinesRequest(getActivity().getApplicationContext());
|
||||||
|
|
||||||
final String sessionId = ((MainActivity)getActivity()).getSessionId();
|
final String sessionId = ((MainActivity)getActivity()).getSessionId();
|
||||||
@ -136,21 +149,21 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (skip == 0) skip = m_articles.size();
|
if (skip == 0) skip = m_articles.size();
|
||||||
|
} else {
|
||||||
|
setLoadingStatus(R.string.blank, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
final int fskip = skip;
|
final int fskip = skip;
|
||||||
|
|
||||||
req.setOffset(skip);
|
req.setOffset(skip);
|
||||||
|
|
||||||
setLoadingStatus(R.string.blank, true);
|
|
||||||
|
|
||||||
HashMap<String,String> map = new HashMap<String,String>() {
|
HashMap<String,String> map = new HashMap<String,String>() {
|
||||||
{
|
{
|
||||||
put("op", "getHeadlines");
|
put("op", "getHeadlines");
|
||||||
put("sid", sessionId);
|
put("sid", sessionId);
|
||||||
put("feed_id", String.valueOf(m_feed.id));
|
put("feed_id", String.valueOf(m_feed.id));
|
||||||
put("show_content", "true");
|
put("show_content", "true");
|
||||||
put("limit", String.valueOf(30));
|
put("limit", String.valueOf(HEADLINES_REQUEST_SIZE));
|
||||||
put("offset", String.valueOf(0));
|
put("offset", String.valueOf(0));
|
||||||
put("view_mode", showUnread ? "adaptive" : "all_articles");
|
put("view_mode", showUnread ? "adaptive" : "all_articles");
|
||||||
put("skip", String.valueOf(fskip));
|
put("skip", String.valueOf(fskip));
|
||||||
@ -170,6 +183,7 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener {
|
|||||||
out.putParcelable("articles", m_articles);
|
out.putParcelable("articles", m_articles);
|
||||||
out.putInt("activeArticleId", m_activeArticleId);
|
out.putInt("activeArticleId", m_activeArticleId);
|
||||||
out.putParcelable("selectedArticles", m_selectedArticles);
|
out.putParcelable("selectedArticles", m_selectedArticles);
|
||||||
|
out.putBoolean("canLoadMore", m_canLoadMore);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLoadingStatus(int status, boolean showProgress) {
|
public void setLoadingStatus(int status, boolean showProgress) {
|
||||||
@ -203,31 +217,43 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener {
|
|||||||
Type listType = new TypeToken<List<Article>>() {}.getType();
|
Type listType = new TypeToken<List<Article>>() {}.getType();
|
||||||
final List<Article> articles = new Gson().fromJson(content, listType);
|
final List<Article> articles = new Gson().fromJson(content, listType);
|
||||||
|
|
||||||
|
while (m_articles.size() > HEADLINES_BUFFER_MAX)
|
||||||
|
m_articles.remove(0);
|
||||||
|
|
||||||
if (m_offset == 0)
|
if (m_offset == 0)
|
||||||
m_articles.clear();
|
m_articles.clear();
|
||||||
|
else
|
||||||
|
m_articles.remove(m_articles.size()-1); // remove previous placeholder
|
||||||
|
|
||||||
int last_position = m_articles.size();
|
int last_position = m_articles.size();
|
||||||
|
|
||||||
for (Article f : articles)
|
for (Article f : articles)
|
||||||
m_articles.add(f);
|
m_articles.add(f);
|
||||||
|
|
||||||
|
if (articles.size() == HEADLINES_REQUEST_SIZE) {
|
||||||
|
Article placeholder = new Article(-1);
|
||||||
|
m_articles.add(placeholder);
|
||||||
|
|
||||||
|
m_canLoadMore = true;
|
||||||
|
} else {
|
||||||
|
m_canLoadMore = false;
|
||||||
|
}
|
||||||
|
|
||||||
m_adapter.notifyDataSetChanged();
|
m_adapter.notifyDataSetChanged();
|
||||||
|
|
||||||
ListView list = (ListView)getView().findViewById(R.id.headlines);
|
/* ListView list = (ListView)getView().findViewById(R.id.headlines);
|
||||||
|
|
||||||
if (list != null && m_offset != 0 && articles.size() > 0) {
|
if (list != null && m_offset != 0 && articles.size() > 0) {
|
||||||
list.setSelection(last_position-1);
|
list.setSelection(last_position-1);
|
||||||
}
|
} */
|
||||||
|
|
||||||
MainActivity activity = (MainActivity)getActivity();
|
|
||||||
activity.setCanLoadMore(articles.size() >= 30);
|
|
||||||
activity.initMainMenu();
|
|
||||||
|
|
||||||
if (m_articles.size() == 0)
|
if (m_articles.size() == 0)
|
||||||
setLoadingStatus(R.string.no_headlines_to_display, false);
|
setLoadingStatus(R.string.no_headlines_to_display, false);
|
||||||
else
|
else
|
||||||
setLoadingStatus(R.string.blank, false);
|
setLoadingStatus(R.string.blank, false);
|
||||||
|
|
||||||
|
m_refreshInProgress = false;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,6 +268,7 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener {
|
|||||||
} else {
|
} else {
|
||||||
setLoadingStatus(getErrorMessage(), false);
|
setLoadingStatus(getErrorMessage(), false);
|
||||||
}
|
}
|
||||||
|
m_refreshInProgress = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOffset(int skip) {
|
public void setOffset(int skip) {
|
||||||
@ -255,8 +282,9 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener {
|
|||||||
public static final int VIEW_NORMAL = 0;
|
public static final int VIEW_NORMAL = 0;
|
||||||
public static final int VIEW_UNREAD = 1;
|
public static final int VIEW_UNREAD = 1;
|
||||||
public static final int VIEW_SELECTED = 2;
|
public static final int VIEW_SELECTED = 2;
|
||||||
|
public static final int VIEW_LOADMORE = 3;
|
||||||
|
|
||||||
public static final int VIEW_COUNT = VIEW_SELECTED+1;
|
public static final int VIEW_COUNT = VIEW_LOADMORE+1;
|
||||||
|
|
||||||
public ArticleListAdapter(Context context, int textViewResourceId, ArrayList<Article> items) {
|
public ArticleListAdapter(Context context, int textViewResourceId, ArrayList<Article> items) {
|
||||||
super(context, textViewResourceId, items);
|
super(context, textViewResourceId, items);
|
||||||
@ -271,7 +299,9 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener {
|
|||||||
public int getItemViewType(int position) {
|
public int getItemViewType(int position) {
|
||||||
Article a = items.get(position);
|
Article a = items.get(position);
|
||||||
|
|
||||||
if (a.id == m_activeArticleId) {
|
if (a.id == -1) {
|
||||||
|
return VIEW_LOADMORE;
|
||||||
|
} else if (a.id == m_activeArticleId) {
|
||||||
return VIEW_SELECTED;
|
return VIEW_SELECTED;
|
||||||
} else if (a.unread) {
|
} else if (a.unread) {
|
||||||
return VIEW_UNREAD;
|
return VIEW_UNREAD;
|
||||||
@ -291,6 +321,9 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener {
|
|||||||
int layoutId = R.layout.headlines_row;
|
int layoutId = R.layout.headlines_row;
|
||||||
|
|
||||||
switch (getItemViewType(position)) {
|
switch (getItemViewType(position)) {
|
||||||
|
case VIEW_LOADMORE:
|
||||||
|
layoutId = R.layout.headlines_row_loadmore;
|
||||||
|
break;
|
||||||
case VIEW_UNREAD:
|
case VIEW_UNREAD:
|
||||||
layoutId = R.layout.headlines_row_unread;
|
layoutId = R.layout.headlines_row_unread;
|
||||||
break;
|
break;
|
||||||
@ -439,4 +472,16 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener {
|
|||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
|
||||||
|
if (!m_refreshInProgress && m_canLoadMore && firstVisibleItem + visibleItemCount == m_articles.size()) {
|
||||||
|
refresh(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onScrollStateChanged(AbsListView view, int scrollState) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ public class MainActivity extends FragmentActivity implements FeedsFragment.OnFe
|
|||||||
private boolean m_smallScreenMode;
|
private boolean m_smallScreenMode;
|
||||||
private boolean m_unreadOnly = true;
|
private boolean m_unreadOnly = true;
|
||||||
private boolean m_unreadArticlesOnly = true;
|
private boolean m_unreadArticlesOnly = true;
|
||||||
private boolean m_canLoadMore = true;
|
//private boolean m_canLoadMore = true;
|
||||||
private boolean m_compatMode = false;
|
private boolean m_compatMode = false;
|
||||||
private boolean m_enableCats = false;
|
private boolean m_enableCats = false;
|
||||||
private int m_apiLevel = 0;
|
private int m_apiLevel = 0;
|
||||||
@ -302,7 +302,7 @@ public class MainActivity extends FragmentActivity implements FeedsFragment.OnFe
|
|||||||
m_activeFeed = savedInstanceState.getParcelable("activeFeed");
|
m_activeFeed = savedInstanceState.getParcelable("activeFeed");
|
||||||
m_selectedArticle = savedInstanceState.getParcelable("selectedArticle");
|
m_selectedArticle = savedInstanceState.getParcelable("selectedArticle");
|
||||||
m_unreadArticlesOnly = savedInstanceState.getBoolean("unreadArticlesOnly");
|
m_unreadArticlesOnly = savedInstanceState.getBoolean("unreadArticlesOnly");
|
||||||
m_canLoadMore = savedInstanceState.getBoolean("canLoadMore");
|
//m_canLoadMore = savedInstanceState.getBoolean("canLoadMore");
|
||||||
m_activeCategory = savedInstanceState.getParcelable("activeCategory");
|
m_activeCategory = savedInstanceState.getParcelable("activeCategory");
|
||||||
m_apiLevel = savedInstanceState.getInt("apiLevel");
|
m_apiLevel = savedInstanceState.getInt("apiLevel");
|
||||||
}
|
}
|
||||||
@ -397,7 +397,7 @@ public class MainActivity extends FragmentActivity implements FeedsFragment.OnFe
|
|||||||
out.putParcelable("activeFeed", m_activeFeed);
|
out.putParcelable("activeFeed", m_activeFeed);
|
||||||
out.putParcelable("selectedArticle", m_selectedArticle);
|
out.putParcelable("selectedArticle", m_selectedArticle);
|
||||||
out.putBoolean("unreadArticlesOnly", m_unreadArticlesOnly);
|
out.putBoolean("unreadArticlesOnly", m_unreadArticlesOnly);
|
||||||
out.putBoolean("canLoadMore", m_canLoadMore);
|
//out.putBoolean("canLoadMore", m_canLoadMore);
|
||||||
out.putParcelable("activeCategory", m_activeCategory);
|
out.putParcelable("activeCategory", m_activeCategory);
|
||||||
out.putInt("apiLevel", m_apiLevel);
|
out.putInt("apiLevel", m_apiLevel);
|
||||||
}
|
}
|
||||||
@ -581,7 +581,6 @@ public class MainActivity extends FragmentActivity implements FeedsFragment.OnFe
|
|||||||
dialog = builder.create();
|
dialog = builder.create();
|
||||||
dialog.show();
|
dialog.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
case R.id.headlines_mark_as_read:
|
case R.id.headlines_mark_as_read:
|
||||||
if (hf != null) {
|
if (hf != null) {
|
||||||
@ -590,14 +589,7 @@ public class MainActivity extends FragmentActivity implements FeedsFragment.OnFe
|
|||||||
for (Article a : articles)
|
for (Article a : articles)
|
||||||
a.unread = false;
|
a.unread = false;
|
||||||
|
|
||||||
ApiRequest req = new ApiRequest(getApplicationContext()) {
|
ApiRequest req = new ApiRequest(getApplicationContext());
|
||||||
@Override
|
|
||||||
protected void onPostExecute(JsonElement result) {
|
|
||||||
if (result != null) {
|
|
||||||
viewFeed(m_activeFeed, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
final String articleIds = articlesToIdString(articles);
|
final String articleIds = articlesToIdString(articles);
|
||||||
|
|
||||||
@ -613,7 +605,6 @@ public class MainActivity extends FragmentActivity implements FeedsFragment.OnFe
|
|||||||
};
|
};
|
||||||
|
|
||||||
req.execute(map);
|
req.execute(map);
|
||||||
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case R.id.share_article:
|
case R.id.share_article:
|
||||||
@ -736,9 +727,9 @@ public class MainActivity extends FragmentActivity implements FeedsFragment.OnFe
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCanLoadMore(boolean canLoadMore) {
|
/* public void setCanLoadMore(boolean canLoadMore) {
|
||||||
m_canLoadMore = canLoadMore;
|
m_canLoadMore = canLoadMore;
|
||||||
}
|
} */
|
||||||
|
|
||||||
public void initMainMenu() {
|
public void initMainMenu() {
|
||||||
if (m_menu != null) {
|
if (m_menu != null) {
|
||||||
|
Loading…
Reference in New Issue
Block a user