Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Add pull-to-refresh #11

Merged
merged 5 commits into from

2 participants

@richsage
Owner

This adds pull-to-refresh functionality to listings:

  • Event listings (Hot/Upcoming/Past)
  • Talk listings for events
  • Event comments
  • Talk comments

This uses the functionality provided by the pull-to-refresh widget developed by @johannilsson

@Tocacar
Owner

I have problems building this due to 2 errors:

  • in EventTalks.java, line 106, you're passing int, int, string to loadTalks() where it should be int, string, string

  • updateSubtitle() method in the same class is declared as void but returns 'talkCount'

@richsage
Owner

OK, those errors should be fixed now.

@Tocacar
Owner

All works fine on my mobile. An interesting observation is that, when a list is shorter than the page height, a 'Tap to Refresh' bar is displayed, however, when the list extends off the page, you are able to pull-to-refresh

http://imgur.com/4iGTdwz

@Tocacar Tocacar merged commit a0b8e37 into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 5, 2014
  1. @richsage
  2. @richsage
  3. @richsage

    Add pull-to-refresh to event comments.

    richsage authored
    Also add missing onRefreshComplete to Talk lists.
  4. @richsage
  5. @richsage

    Fix errors in building.

    richsage authored
This page is out of date. Refresh to see the latest.
View
BIN  source/res/drawable-hdpi/ic_pulltorefresh_arrow.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  source/res/drawable-ldpi/ic_pulltorefresh_arrow.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  source/res/drawable-mdpi/ic_pulltorefresh_arrow.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
5 source/res/layout/comments.xml
@@ -12,13 +12,14 @@
android:orientation="vertical"
android:layout_weight="1">
- <ListView
+ <com.markupartist.android.widget.PullToRefreshListView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbarAlwaysDrawVerticalTrack="true"
android:scrollbars="vertical"
android:id="@+id/EventDetailComments"
- android:clickable="false"></ListView>
+ android:clickable="false" />
+
</LinearLayout>
<Button
View
4 source/res/layout/eventtalks.xml
@@ -6,10 +6,10 @@
android:layout_height="fill_parent"
android:layout_width="fill_parent">
- <ListView
+ <com.markupartist.android.widget.PullToRefreshListView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbarAlwaysDrawVerticalTrack="true"
android:scrollbars="vertical"
- android:id="@+id/ListViewEventTalks"></ListView>
+ android:id="@+id/ListViewEventTalks"/>
</LinearLayout>
View
69 source/res/layout/pull_to_refresh_header.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 Johan Nilsson <http://markupartist.com>
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:paddingTop="10dip"
+ android:paddingBottom="15dip"
+ android:gravity="center"
+ android:id="@+id/pull_to_refresh_header"
+ >
+ <ProgressBar
+ android:id="@+id/pull_to_refresh_progress"
+ android:indeterminate="true"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="30dip"
+ android:layout_marginRight="20dip"
+ android:layout_marginTop="10dip"
+ android:visibility="gone"
+ android:layout_centerVertical="true"
+ style="?android:attr/progressBarStyleSmall"
+ />
+ <ImageView
+ android:id="@+id/pull_to_refresh_image"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="30dip"
+ android:layout_marginRight="20dip"
+ android:visibility="gone"
+ android:layout_gravity="center"
+ android:gravity="center"
+ android:src="@drawable/ic_pulltorefresh_arrow"
+ />
+ <TextView
+ android:id="@+id/pull_to_refresh_text"
+ android:text="@string/pull_to_refresh_tap_label"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textStyle="bold"
+ android:paddingTop="5dip"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:gravity="center"
+ />
+ <TextView
+ android:id="@+id/pull_to_refresh_updated_at"
+ android:layout_below="@+id/pull_to_refresh_text"
+ android:visibility="gone"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:gravity="center"
+ />
+</RelativeLayout>
View
6 source/res/values/strings.xml
@@ -113,4 +113,10 @@
<string name="activityEventDetailFailedJSON">Couldn\'t retrieve event details</string>
<string name="activityTalkCommentsFailedJSON">Couldn\'t retrieve talk details</string>
+ <!-- Pull-to-refresh copy -->
+ <string name="pull_to_refresh_pull_label">Pull to refresh…</string>
+ <string name="pull_to_refresh_release_label">Release to refresh…</string>
+ <string name="pull_to_refresh_refreshing_label">Loading…</string>
+ <string name="pull_to_refresh_tap_label">Tap to refresh…</string>
+
</resources>
View
410 source/src/com/markupartist/android/widget/PullToRefreshListView.java
@@ -0,0 +1,410 @@
+package com.markupartist.android.widget;
+
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.LinearInterpolator;
+import android.view.animation.RotateAnimation;
+import android.widget.AbsListView;
+import android.widget.ImageView;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+import android.widget.ProgressBar;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+import android.widget.AbsListView.OnScrollListener;
+
+import in.joind.R;
+
+public class PullToRefreshListView extends ListView implements OnScrollListener {
+
+ private static final int TAP_TO_REFRESH = 1;
+ private static final int PULL_TO_REFRESH = 2;
+ private static final int RELEASE_TO_REFRESH = 3;
+ private static final int REFRESHING = 4;
+
+ private static final String TAG = "PullToRefreshListView";
+
+ private OnRefreshListener mOnRefreshListener;
+
+ /**
+ * Listener that will receive notifications every time the list scrolls.
+ */
+ private OnScrollListener mOnScrollListener;
+ private LayoutInflater mInflater;
+
+ private RelativeLayout mRefreshView;
+ private TextView mRefreshViewText;
+ private ImageView mRefreshViewImage;
+ private ProgressBar mRefreshViewProgress;
+ private TextView mRefreshViewLastUpdated;
+
+ private int mCurrentScrollState;
+ private int mRefreshState;
+
+ private RotateAnimation mFlipAnimation;
+ private RotateAnimation mReverseFlipAnimation;
+
+ private int mRefreshViewHeight;
+ private int mRefreshOriginalTopPadding;
+ private int mLastMotionY;
+
+ private boolean mBounceHack;
+
+ public PullToRefreshListView(Context context) {
+ super(context);
+ init(context);
+ }
+
+ public PullToRefreshListView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(context);
+ }
+
+ public PullToRefreshListView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init(context);
+ }
+
+ private void init(Context context) {
+ // Load all of the animations we need in code rather than through XML
+ mFlipAnimation = new RotateAnimation(0, -180,
+ RotateAnimation.RELATIVE_TO_SELF, 0.5f,
+ RotateAnimation.RELATIVE_TO_SELF, 0.5f);
+ mFlipAnimation.setInterpolator(new LinearInterpolator());
+ mFlipAnimation.setDuration(250);
+ mFlipAnimation.setFillAfter(true);
+ mReverseFlipAnimation = new RotateAnimation(-180, 0,
+ RotateAnimation.RELATIVE_TO_SELF, 0.5f,
+ RotateAnimation.RELATIVE_TO_SELF, 0.5f);
+ mReverseFlipAnimation.setInterpolator(new LinearInterpolator());
+ mReverseFlipAnimation.setDuration(250);
+ mReverseFlipAnimation.setFillAfter(true);
+
+ mInflater = (LayoutInflater) context.getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
+
+ mRefreshView = (RelativeLayout) mInflater.inflate(
+ R.layout.pull_to_refresh_header, this, false);
+ mRefreshViewText =
+ (TextView) mRefreshView.findViewById(R.id.pull_to_refresh_text);
+ mRefreshViewImage =
+ (ImageView) mRefreshView.findViewById(R.id.pull_to_refresh_image);
+ mRefreshViewProgress =
+ (ProgressBar) mRefreshView.findViewById(R.id.pull_to_refresh_progress);
+ mRefreshViewLastUpdated =
+ (TextView) mRefreshView.findViewById(R.id.pull_to_refresh_updated_at);
+
+ mRefreshViewImage.setMinimumHeight(50);
+ mRefreshView.setOnClickListener(new OnClickRefreshListener());
+ mRefreshOriginalTopPadding = mRefreshView.getPaddingTop();
+
+ mRefreshState = TAP_TO_REFRESH;
+
+ addHeaderView(mRefreshView);
+
+ super.setOnScrollListener(this);
+
+ measureView(mRefreshView);
+ mRefreshViewHeight = mRefreshView.getMeasuredHeight();
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ setSelection(1);
+ }
+
+ @Override
+ public void setAdapter(ListAdapter adapter) {
+ super.setAdapter(adapter);
+ setSelection(1);
+ }
+
+ /**
+ * Set the listener that will receive notifications every time the list
+ * scrolls.
+ *
+ * @param l The scroll listener.
+ */
+ @Override
+ public void setOnScrollListener(AbsListView.OnScrollListener l) {
+ mOnScrollListener = l;
+ }
+
+ /**
+ * Register a callback to be invoked when this list should be refreshed.
+ *
+ * @param onRefreshListener The callback to run.
+ */
+ public void setOnRefreshListener(OnRefreshListener onRefreshListener) {
+ mOnRefreshListener = onRefreshListener;
+ }
+
+ /**
+ * Set a text to represent when the list was last updated.
+ * @param lastUpdated Last updated at.
+ */
+ public void setLastUpdated(CharSequence lastUpdated) {
+ if (lastUpdated != null) {
+ mRefreshViewLastUpdated.setVisibility(View.VISIBLE);
+ mRefreshViewLastUpdated.setText(lastUpdated);
+ } else {
+ mRefreshViewLastUpdated.setVisibility(View.GONE);
+ }
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ final int y = (int) event.getY();
+ mBounceHack = false;
+
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_UP:
+ if (!isVerticalScrollBarEnabled()) {
+ setVerticalScrollBarEnabled(true);
+ }
+ if (getFirstVisiblePosition() == 0 && mRefreshState != REFRESHING) {
+ if ((mRefreshView.getBottom() >= mRefreshViewHeight
+ || mRefreshView.getTop() >= 0)
+ && mRefreshState == RELEASE_TO_REFRESH) {
+ // Initiate the refresh
+ mRefreshState = REFRESHING;
+ prepareForRefresh();
+ onRefresh();
+ } else if (mRefreshView.getBottom() < mRefreshViewHeight
+ || mRefreshView.getTop() <= 0) {
+ // Abort refresh and scroll down below the refresh view
+ resetHeader();
+ setSelection(1);
+ }
+ }
+ break;
+ case MotionEvent.ACTION_DOWN:
+ mLastMotionY = y;
+ break;
+ case MotionEvent.ACTION_MOVE:
+ applyHeaderPadding(event);
+ break;
+ }
+ return super.onTouchEvent(event);
+ }
+
+ private void applyHeaderPadding(MotionEvent ev) {
+ // getHistorySize has been available since API 1
+ int pointerCount = ev.getHistorySize();
+
+ for (int p = 0; p < pointerCount; p++) {
+ if (mRefreshState == RELEASE_TO_REFRESH) {
+ if (isVerticalFadingEdgeEnabled()) {
+ setVerticalScrollBarEnabled(false);
+ }
+
+ int historicalY = (int) ev.getHistoricalY(p);
+
+ // Calculate the padding to apply, we divide by 1.7 to
+ // simulate a more resistant effect during pull.
+ int topPadding = (int) (((historicalY - mLastMotionY)
+ - mRefreshViewHeight) / 1.7);
+
+ mRefreshView.setPadding(
+ mRefreshView.getPaddingLeft(),
+ topPadding,
+ mRefreshView.getPaddingRight(),
+ mRefreshView.getPaddingBottom());
+ }
+ }
+ }
+
+ /**
+ * Sets the header padding back to original size.
+ */
+ private void resetHeaderPadding() {
+ mRefreshView.setPadding(
+ mRefreshView.getPaddingLeft(),
+ mRefreshOriginalTopPadding,
+ mRefreshView.getPaddingRight(),
+ mRefreshView.getPaddingBottom());
+ }
+
+ /**
+ * Resets the header to the original state.
+ */
+ private void resetHeader() {
+ if (mRefreshState != TAP_TO_REFRESH) {
+ mRefreshState = TAP_TO_REFRESH;
+
+ resetHeaderPadding();
+
+ // Set refresh view text to the pull label
+ mRefreshViewText.setText(R.string.pull_to_refresh_tap_label);
+ // Replace refresh drawable with arrow drawable
+ mRefreshViewImage.setImageResource(R.drawable.ic_pulltorefresh_arrow);
+ // Clear the full rotation animation
+ mRefreshViewImage.clearAnimation();
+ // Hide progress bar and arrow.
+ mRefreshViewImage.setVisibility(View.GONE);
+ mRefreshViewProgress.setVisibility(View.GONE);
+ }
+ }
+
+ private void measureView(View child) {
+ ViewGroup.LayoutParams p = child.getLayoutParams();
+ if (p == null) {
+ p = new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT);
+ }
+
+ int childWidthSpec = ViewGroup.getChildMeasureSpec(0,
+ 0 + 0, p.width);
+ int lpHeight = p.height;
+ int childHeightSpec;
+ if (lpHeight > 0) {
+ childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
+ } else {
+ childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+ }
+ child.measure(childWidthSpec, childHeightSpec);
+ }
+
+ @Override
+ public void onScroll(AbsListView view, int firstVisibleItem,
+ int visibleItemCount, int totalItemCount) {
+ // When the refresh view is completely visible, change the text to say
+ // "Release to refresh..." and flip the arrow drawable.
+ if (mCurrentScrollState == SCROLL_STATE_TOUCH_SCROLL
+ && mRefreshState != REFRESHING) {
+ if (firstVisibleItem == 0) {
+ mRefreshViewImage.setVisibility(View.VISIBLE);
+ if ((mRefreshView.getBottom() >= mRefreshViewHeight + 20
+ || mRefreshView.getTop() >= 0)
+ && mRefreshState != RELEASE_TO_REFRESH) {
+ mRefreshViewText.setText(R.string.pull_to_refresh_release_label);
+ mRefreshViewImage.clearAnimation();
+ mRefreshViewImage.startAnimation(mFlipAnimation);
+ mRefreshState = RELEASE_TO_REFRESH;
+ } else if (mRefreshView.getBottom() < mRefreshViewHeight + 20
+ && mRefreshState != PULL_TO_REFRESH) {
+ mRefreshViewText.setText(R.string.pull_to_refresh_pull_label);
+ if (mRefreshState != TAP_TO_REFRESH) {
+ mRefreshViewImage.clearAnimation();
+ mRefreshViewImage.startAnimation(mReverseFlipAnimation);
+ }
+ mRefreshState = PULL_TO_REFRESH;
+ }
+ } else {
+ mRefreshViewImage.setVisibility(View.GONE);
+ resetHeader();
+ }
+ } else if (mCurrentScrollState == SCROLL_STATE_FLING
+ && firstVisibleItem == 0
+ && mRefreshState != REFRESHING) {
+ setSelection(1);
+ mBounceHack = true;
+ } else if (mBounceHack && mCurrentScrollState == SCROLL_STATE_FLING) {
+ setSelection(1);
+ }
+
+ if (mOnScrollListener != null) {
+ mOnScrollListener.onScroll(view, firstVisibleItem,
+ visibleItemCount, totalItemCount);
+ }
+ }
+
+ @Override
+ public void onScrollStateChanged(AbsListView view, int scrollState) {
+ mCurrentScrollState = scrollState;
+
+ if (mCurrentScrollState == SCROLL_STATE_IDLE) {
+ mBounceHack = false;
+ }
+
+ if (mOnScrollListener != null) {
+ mOnScrollListener.onScrollStateChanged(view, scrollState);
+ }
+ }
+
+ public void prepareForRefresh() {
+ resetHeaderPadding();
+
+ mRefreshViewImage.setVisibility(View.GONE);
+ // We need this hack, otherwise it will keep the previous drawable.
+ mRefreshViewImage.setImageDrawable(null);
+ mRefreshViewProgress.setVisibility(View.VISIBLE);
+
+ // Set refresh view text to the refreshing label
+ mRefreshViewText.setText(R.string.pull_to_refresh_refreshing_label);
+
+ mRefreshState = REFRESHING;
+ }
+
+ public void onRefresh() {
+ Log.d(TAG, "onRefresh");
+
+ if (mOnRefreshListener != null) {
+ mOnRefreshListener.onRefresh();
+ }
+ }
+
+ /**
+ * Resets the list to a normal state after a refresh.
+ * @param lastUpdated Last updated at.
+ */
+ public void onRefreshComplete(CharSequence lastUpdated) {
+ setLastUpdated(lastUpdated);
+ onRefreshComplete();
+ }
+
+ /**
+ * Resets the list to a normal state after a refresh.
+ */
+ public void onRefreshComplete() {
+ Log.d(TAG, "onRefreshComplete");
+
+ resetHeader();
+
+ // If refresh view is visible when loading completes, scroll down to
+ // the next item.
+ if (getFirstVisiblePosition() == 0) {
+ invalidateViews();
+ setSelection(1);
+ }
+ }
+
+ /**
+ * Invoked when the refresh view is clicked on. This is mainly used when
+ * there's only a few items in the list and it's not possible to drag the
+ * list.
+ */
+ private class OnClickRefreshListener implements OnClickListener {
+
+ @Override
+ public void onClick(View v) {
+ if (mRefreshState != REFRESHING) {
+ prepareForRefresh();
+ onRefresh();
+ }
+ }
+
+ }
+
+ /**
+ * Interface definition for a callback to be invoked when list should be
+ * refreshed.
+ */
+ public interface OnRefreshListener {
+ /**
+ * Called when the list should be refreshed.
+ * <p>
+ * A call to {@link PullToRefreshListView #onRefreshComplete()} is
+ * expected to indicate that the refresh has completed.
+ */
+ public void onRefresh();
+ }
+}
View
18 source/src/in/joind/EventComments.java
@@ -25,6 +25,8 @@
import android.widget.ListView;
import android.widget.TextView;
+import com.markupartist.android.widget.PullToRefreshListView;
+
public class EventComments extends JIActivity implements OnClickListener {
private JIEventCommentAdapter m_eventCommentAdapter; // adapter for listview
private JSONObject eventJSON;
@@ -55,7 +57,7 @@ public void onCreate(Bundle savedInstanceState) {
// Initialize comment list
ArrayList<JSONObject> m_eventcomments = new ArrayList<JSONObject>();
m_eventCommentAdapter = new JIEventCommentAdapter(this, R.layout.talkrow, m_eventcomments);
- ListView eventcommentlist =(ListView)findViewById(R.id.EventDetailComments);
+ final PullToRefreshListView eventcommentlist = (PullToRefreshListView) findViewById(R.id.EventDetailComments);
eventcommentlist.setAdapter(m_eventCommentAdapter);
// Display the cached event comments
@@ -66,6 +68,18 @@ public void onCreate(Bundle savedInstanceState) {
Button button = (Button)findViewById(R.id.ButtonNewComment);
button.setOnClickListener(this);
+ eventcommentlist.setOnRefreshListener(new PullToRefreshListView.OnRefreshListener() {
+ @Override
+ public void onRefresh() {
+ try {
+ loadEventComments (event_id, eventJSON.getString("comments_uri"));
+ } catch (JSONException e) {
+ android.util.Log.e(JIActivity.LOG_JOINDIN_APP, "No comments URI available");
+ eventcommentlist.onRefreshComplete();
+ }
+ }
+ });
+
// Load new comments from the joind.in API and display them
try {
loadEventComments (event_id, this.eventJSON.getString("comments_uri"));
@@ -132,6 +146,8 @@ public int displayEventComments (int event_id) {
getSupportActionBar().setSubtitle(String.format(getString(R.string.generalCommentPlural), count));
}
+ ((PullToRefreshListView) findViewById(R.id.EventDetailComments)).onRefreshComplete();
+
// Return number of event comments.
return count;
}
View
33 source/src/in/joind/EventListFragment.java
@@ -15,11 +15,14 @@
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Filter;
+import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
+import com.markupartist.android.widget.PullToRefreshListView;
+
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -48,12 +51,29 @@ public void onAttach(Activity activity) {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View view = super.onCreateView(inflater, container, savedInstanceState);
+ ViewGroup viewGroup = (ViewGroup) super.onCreateView(inflater, container, savedInstanceState);
+
+ View lvOld = viewGroup.findViewById(android.R.id.list);
+
+ // Use the pull-to-refresh ListView, instead of a normal ListView
+ final PullToRefreshListView listView = new PullToRefreshListView(getActivity());
+ listView.setId(android.R.id.list);
+ listView.setLayoutParams(new FrameLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
+ listView.setDrawSelectorOnTop(false);
+
+ FrameLayout parent = (FrameLayout) lvOld.getParent();
+ parent.removeView(lvOld);
+ lvOld.setVisibility(View.GONE);
+
+ parent.addView(listView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
+
+ // Populate our list adapter
ArrayList<JSONObject> m_events = new ArrayList<JSONObject>();
m_eventAdapter = new JIEventAdapter(getActivity(), R.layout.eventrow, m_events);
setListAdapter(m_eventAdapter);
- return view;
+ return viewGroup;
}
@Override
@@ -110,6 +130,12 @@ public void onItemClick(AdapterView<?> parent, View view, int pos, long id) {
startActivity(myIntent);
}
});
+ ((PullToRefreshListView) getListView()).setOnRefreshListener(new PullToRefreshListView.OnRefreshListener() {
+ @Override
+ public void onRefresh() {
+ loadEvents(EventListFragment.this.getTag());
+ }
+ });
}
// Display events by populating the m_eventAdapter (custom list) with items loaded from DB
@@ -127,6 +153,9 @@ public int displayEvents(final String eventType) {
// Tell the adapter that our data set has changed so it can update it
m_eventAdapter.notifyDataSetChanged();
+ if (listView != null) {
+ ((PullToRefreshListView) getListView()).onRefreshComplete();
+ }
parentActivity.setEventsCountTitle(count);
View
22 source/src/in/joind/EventTalks.java
@@ -33,6 +33,8 @@
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
+import com.markupartist.android.widget.PullToRefreshListView;
+
public class EventTalks extends JIActivity implements OnClickListener {
private JITalkAdapter m_talkAdapter; // adapter for listview
private JSONObject eventJSON;
@@ -80,9 +82,12 @@ public void onCreate(Bundle savedInstanceState) {
tz = TimeZone.getDefault();
}
m_talkAdapter = new JITalkAdapter(this, R.layout.talkrow, m_talks, tz);
- ListView talklist = (ListView) findViewById(R.id.ListViewEventTalks);
+ final PullToRefreshListView talklist = (PullToRefreshListView) findViewById(R.id.ListViewEventTalks);
talklist.setAdapter(m_talkAdapter);
+ // Display cached talks, optionally filtered by a track (by URI)
+ final String trackURI = (this.trackJSON != null) ? this.trackJSON.optString("uri") : "";
+
// Add listview listener so when we click on an talk, we can display details
talklist.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int pos, long id) {
@@ -94,9 +99,18 @@ public void onItemClick(AdapterView<?> parent, View view, int pos, long id) {
startActivity(myIntent);
}
});
+ talklist.setOnRefreshListener(new PullToRefreshListView.OnRefreshListener() {
+ @Override
+ public void onRefresh() {
+ try {
+ loadTalks(eventRowID, trackURI, eventJSON.getString("talks_uri"));
+ } catch (JSONException e) {
+ android.util.Log.e(JIActivity.LOG_JOINDIN_APP, "No talks URI available");
+ talklist.onRefreshComplete();
+ }
+ }
+ });
- // Display cached talks, optionally filtered by a track (by URI)
- String trackURI = (this.trackJSON != null) ? this.trackJSON.optString("uri") : "";
displayTalks(eventRowID, trackURI);
// Load new talks (in background)
@@ -139,6 +153,8 @@ protected void updateSubtitle(int talkCount) {
talksFound += String.format(getString(R.string.generalEventTalksPlural), talkCount);
}
getSupportActionBar().setSubtitle(talksFound);
+
+ ((PullToRefreshListView) findViewById(R.id.ListViewEventTalks)).onRefreshComplete();
}
// Load talks in new thread...
View
19 source/src/in/joind/TalkComments.java
@@ -28,6 +28,7 @@
import android.widget.Toast;
import com.crashlytics.android.Crashlytics;
+import com.markupartist.android.widget.PullToRefreshListView;
public class TalkComments extends JIActivity implements OnClickListener {
private JITalkCommentAdapter m_talkCommentAdapter; // adapter for listview
@@ -68,13 +69,25 @@ public void onCreate(Bundle savedInstanceState) {
// Initialize comment list
ArrayList<JSONObject> m_talkcomments = new ArrayList<JSONObject>();
m_talkCommentAdapter = new JITalkCommentAdapter(this, R.layout.talkrow, m_talkcomments);
- ListView talkcommentlist = (ListView) findViewById(R.id.EventDetailComments);
+ final PullToRefreshListView talkcommentlist = (PullToRefreshListView) findViewById(R.id.EventDetailComments);
talkcommentlist.setAdapter(m_talkCommentAdapter);
// Display the cached comments
- int talk_id = TalkComments.this.talkJSON.optInt("rowID");
+ final int talk_id = talkJSON.optInt("rowID");
displayTalkComments(talk_id);
+ talkcommentlist.setOnRefreshListener(new PullToRefreshListView.OnRefreshListener() {
+ @Override
+ public void onRefresh() {
+ try {
+ loadTalkComments(talk_id, talkJSON.getString("comments_uri"));
+ } catch (JSONException e) {
+ android.util.Log.e(JIActivity.LOG_JOINDIN_APP, "No comments URI available (talk comments)");
+ talkcommentlist.onRefreshComplete();
+ }
+ }
+ });
+
// Load new comments for this talk and display them
try {
loadTalkComments(talk_id, this.talkJSON.getString("comments_uri"));
@@ -124,6 +137,8 @@ public int displayTalkComments(int talk_id) {
setTitle(String.format(getString(R.string.generalCommentPlural), count));
}
+ ((PullToRefreshListView) findViewById(R.id.EventDetailComments)).onRefreshComplete();
+
// Return the number of comments found
return count;
}
Something went wrong with that request. Please try again.