下來刷新+gallery

廢話少說先上圖

demo 下載地址 http://download.csdn.net/detail/jansin_love/5428921

其中上半部分是一個gallery,下邊是一個listview

UGallery .java

package com.gallery.test;


import android.content.Context;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.widget.Gallery;


public class UGallery extends Gallery {


public UGallery(Context context, AttributeSet attrs) {
super(context, attrs);
}
   
private boolean isScrollingLeft(MotionEvent e1, MotionEvent e2) {
return e2.getX() > e1.getX();
}
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
int keyCode;
if (isScrollingLeft(e1, e2)) {
keyCode = KeyEvent.KEYCODE_DPAD_LEFT;
} else {
keyCode = KeyEvent.KEYCODE_DPAD_RIGHT;
}
onKeyDown(keyCode, null);
return true;
}
}

PullToRefreshListActivity .java

package com.stay.pull;


import android.app.ListActivity;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AdapterView.OnItemSelectedListener;


import com.gallery.test.UGallery;
import com.stay.pull.lib.PullToRefreshBase.OnRefreshListener;
import com.stay.pull.lib.PullToRefreshListView;


public class PullToRefreshListActivity extends ListActivity {


static final int MENU_MANUAL_REFRESH = 0;
static final int MENU_DISABLE_SCROLL = 1;
private PullToRefreshListView mPullRefreshListView;
// Gallery mGallery;
private UGallery uGallery;
private ViewGroup vg;
private LinearLayout change_layout;
private LinearLayout viewGroup;
private LinearLayout title_layout;
private ImageView imageView;
private ImageView[] imageViews;
private TextView[] txt_titles;
private TextView txt_title;
private ListView actualListView;
private Integer[] mImage = { R.drawable.image1, R.drawable.image2,
R.drawable.image3, };
private String[] mtitle = { "這是美麗的風景", "這是可愛的稻草人", "這是迷人的大海" };
private ImageView change_1, change_2, change_3;


@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);


setContentView(R.layout.pull_to_refresh_list);


imageViews = new ImageView[mImage.length];
vg= (ViewGroup) LayoutInflater.from(this).inflate(R.layout.main1, null);
uGallery = (UGallery) vg.findViewById(R.id.gly_images);
change_layout = (LinearLayout) vg.findViewById(R.id.change_layout);
viewGroup = (LinearLayout) vg.findViewById(R.id.viewGroup);
title_layout = (LinearLayout) vg.findViewById(R.id.title_layout);
txt_title = new TextView(this);
title_layout.addView(txt_title);
change_layout.getBackground().setAlpha(180);
uGallery.setAdapter(new ImageAdapter(PullToRefreshListActivity.this));
for (int i = 0; i < mImage.length; i++) {
imageView = new ImageView(this);
imageView.setLayoutParams(new LayoutParams(18, 12));
imageViews[i] = imageView;


if (i == 0) {
// 默認進入程序後第一張圖片被選中;
imageViews[i].setBackgroundResource(R.drawable.selectedflag);
} else {
imageViews[i].setBackgroundResource(R.drawable.unselectedflag);
}


viewGroup.addView(imageView);


}


uGallery.setOnItemSelectedListener(new OnItemSelectedListener() {


@Override
public void onItemSelected(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
txt_title.setText(mtitle[arg2]);
for (int i = 0; i < imageViews.length; i++) {
imageViews[arg2].setBackgroundResource(R.drawable.selectedflag);
if (arg2 != i) {
imageViews[i].setBackgroundResource(R.drawable.unselectedflag);
}
}


}


@Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub


}
});


mPullRefreshListView = (PullToRefreshListView) findViewById(R.id.pull_refresh_list);
mPullRefreshListView.setOnRefreshListener(new OnRefreshListener() {
@Override
public void onRefresh() {
new GetDataTask().execute();
}
});
actualListView = mPullRefreshListView.getRefreshableView();
actualListView.setAdapter(new Mybaseadapter());


}


private class GetDataTask extends AsyncTask<Void, Void, String[]> {


@Override
protected String[] doInBackground(Void... params) {
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
}
return new String[] { "返回數據" };
}


@Override
protected void onPostExecute(String[] result) {
//mAdapter.notifyDataSetChanged();
mPullRefreshListView.onRefreshComplete();


super.onPostExecute(result);
}
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, MENU_MANUAL_REFRESH, 0, "Manual Refresh");
menu.add(
0,
MENU_DISABLE_SCROLL,
1,
mPullRefreshListView.isDisableScrollingWhileRefreshing() ? "Enable Scrolling while Refreshing"
: "Disable Scrolling while Refreshing");
return super.onCreateOptionsMenu(menu);
}


@Override
public boolean onOptionsItemSelected(MenuItem item) {


switch (item.getItemId()) {


case MENU_MANUAL_REFRESH:
new GetDataTask().execute();
mPullRefreshListView.setRefreshing(false);
break;
case MENU_DISABLE_SCROLL:
mPullRefreshListView.setDisableScrollingWhileRefreshing(!mPullRefreshListView
.isDisableScrollingWhileRefreshing());
break;
}


return super.onOptionsItemSelected(item);
}


private class Mybaseadapter extends BaseAdapter {
@Override
public int getCount() {
return 31;
}


@Override
public Object getItem(int position) {
return 0;
}


@Override
public long getItemId(int position) {
return 0;
}


@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (position == 0) {
return vg;
} else {
TextView mTextView = new TextView(PullToRefreshListActivity.this);
mTextView.setText(position - 1 + "");
return mTextView;
}
}


}
private class ImageAdapter extends BaseAdapter {
private Context mContext;
private int i = 0;


public ImageAdapter(Context c) {
mContext = c;
}


@Override
public int getCount() {
return mImage.length;
}


@Override
public Object getItem(int position) {
// TODO Auto-generated method stub


return position;
}


@Override
public long getItemId(int position) {
// TODO Auto-generated method stub


return position;
}


@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub


ImageView i = new ImageView(mContext);
i.setImageResource(mImage[position]);
// i.setScaleType(ImageView.ScaleType.FIT_XY);
i.setLayoutParams(new Gallery.LayoutParams(800, LayoutParams.WRAP_CONTENT));


return i;
}


};
}

下拉刷新的動畫部分

package com.stay.pull.lib;


import android.content.Context;
import android.util.AttributeSet;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.FrameLayout;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;


import com.stay.pull.lib.internal.EmptyViewMethodAccessor;




public abstract class PullToRefreshAdapterViewBase<T extends AbsListView> extends PullToRefreshBase<T> implements
OnScrollListener {


private int lastSavedFirstVisibleItem = -1;
private OnScrollListener onScrollListener;
private OnLastItemVisibleListener onLastItemVisibleListener;
private View emptyView;
private FrameLayout refreshableViewHolder;
private ImageView mTopImageView;


public PullToRefreshAdapterViewBase(Context context) {
super(context);
refreshableView.setOnScrollListener(this);
}


public PullToRefreshAdapterViewBase(Context context, int mode) {
super(context, mode);
refreshableView.setOnScrollListener(this);
}


public PullToRefreshAdapterViewBase(Context context, AttributeSet attrs) {
super(context, attrs);
refreshableView.setOnScrollListener(this);
}


abstract public ContextMenuInfo getContextMenuInfo();


public final void onScroll(final AbsListView view, final int firstVisibleItem, final int visibleItemCount,
final int totalItemCount) {


if (null != onLastItemVisibleListener) {
// detect if last item is visible
if (visibleItemCount > 0 && (firstVisibleItem + visibleItemCount == totalItemCount)) {
// only process first event
if (firstVisibleItem != lastSavedFirstVisibleItem) {
lastSavedFirstVisibleItem = firstVisibleItem;
onLastItemVisibleListener.onLastItemVisible();
}
}
}


if (null != onScrollListener) {
onScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
}
}


public final void onScrollStateChanged(final AbsListView view, final int scrollState) {
if (null != onScrollListener) {
onScrollListener.onScrollStateChanged(view, scrollState);
}
}

public void setBackToTopView(ImageView mTopImageView){
this.mTopImageView = mTopImageView;
mTopImageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (refreshableView instanceof ListView ) {
((ListView)refreshableView).setSelection(0);
}else if(refreshableView instanceof GridView){
((GridView)refreshableView).setSelection(0);
}
}
});
}


/**
* Sets the Empty View to be used by the Adapter View.

* We need it handle it ourselves so that we can Pull-to-Refresh when the
* Empty View is shown.

* Please note, you do <strong>not</strong> usually need to call this method
* yourself. Calling setEmptyView on the AdapterView will automatically call
* this method and set everything up. This includes when the Android
* Framework automatically sets the Empty View based on it's ID.

* @param newEmptyView
*            - Empty View to be used
*/
public final void setEmptyView(View newEmptyView) {
// If we already have an Empty View, remove it
if (null != emptyView) {
refreshableViewHolder.removeView(emptyView);
}


if (null != newEmptyView) {
ViewParent newEmptyViewParent = newEmptyView.getParent();
if (null != newEmptyViewParent && newEmptyViewParent instanceof ViewGroup) {
((ViewGroup) newEmptyViewParent).removeView(newEmptyView);
}


this.refreshableViewHolder.addView(newEmptyView, ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.FILL_PARENT);
}


if (refreshableView instanceof EmptyViewMethodAccessor) {
((EmptyViewMethodAccessor) refreshableView).setEmptyViewInternal(newEmptyView);
} else {
this.refreshableView.setEmptyView(newEmptyView);
}
}


public final void setOnLastItemVisibleListener(OnLastItemVisibleListener listener) {
onLastItemVisibleListener = listener;
}


public final void setOnScrollListener(OnScrollListener listener) {
onScrollListener = listener;
}


protected void addRefreshableView(Context context, T refreshableView) {
refreshableViewHolder = new FrameLayout(context);
refreshableViewHolder.addView(refreshableView, ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.FILL_PARENT);
addView(refreshableViewHolder, new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, 0, 1.0f));
};


protected boolean isReadyForPullDown() {
return isFirstItemVisible();
}


protected boolean isReadyForPullUp() {
return isLastItemVisible();
}


private boolean isFirstItemVisible() {
if (this.refreshableView.getCount() == 0) {
return true;
} else if (refreshableView.getFirstVisiblePosition() == 0) {

final View firstVisibleChild = refreshableView.getChildAt(0);

if (firstVisibleChild != null) {
return firstVisibleChild.getTop() >= refreshableView.getTop();
}
}

return false;
}


private boolean isLastItemVisible() {
final int count = this.refreshableView.getCount();
final int lastVisiblePosition = refreshableView.getLastVisiblePosition();


if (count == 0) {
return true;
} else if (lastVisiblePosition == count - 1) {


final int childIndex = lastVisiblePosition - refreshableView.getFirstVisiblePosition();
final View lastVisibleChild = refreshableView.getChildAt(childIndex);


if (lastVisibleChild != null) {
return lastVisibleChild.getBottom() <= refreshableView.getBottom();
}
}
return false;
}
}



package com.stay.pull.lib;


import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Interpolator;
import android.widget.LinearLayout;


import com.stay.pull.R;
import com.stay.pull.lib.internal.LoadingLayout;


public abstract class PullToRefreshBase<T extends View> extends LinearLayout {


final class SmoothScrollRunnable implements Runnable {


static final int ANIMATION_DURATION_MS = 190;
static final int ANIMATION_FPS = 1000 / 60;


private final Interpolator interpolator;
private final int scrollToY;
private final int scrollFromY;
private final Handler handler;


private boolean continueRunning = true;
private long startTime = -1;
private int currentY = -1;


public SmoothScrollRunnable(Handler handler, int fromY, int toY) {
this.handler = handler;
this.scrollFromY = fromY;
this.scrollToY = toY;
this.interpolator = new AccelerateDecelerateInterpolator();
}


@Override
public void run() {


/**
* Only set startTime if this is the first time we're starting, else
* actually calculate the Y delta
*/
if (startTime == -1) {
startTime = System.currentTimeMillis();
} else {


/**
* We do do all calculations in long to reduce software float
* calculations. We use 1000 as it gives us good accuracy and
* small rounding errors
*/
long normalizedTime = (1000 * (System.currentTimeMillis() - startTime)) / ANIMATION_DURATION_MS;
normalizedTime = Math.max(Math.min(normalizedTime, 1000), 0);


final int deltaY = Math.round((scrollFromY - scrollToY)
* interpolator.getInterpolation(normalizedTime / 1000f));
this.currentY = scrollFromY - deltaY;
setHeaderScroll(currentY);
}


// If we're not at the target Y, keep going...
if (continueRunning && scrollToY != currentY) {
handler.postDelayed(this, ANIMATION_FPS);
}
}


public void stop() {
this.continueRunning = false;
this.handler.removeCallbacks(this);
}
};


// ===========================================================
// Constants
// ===========================================================


static final float FRICTION = 2.0f;


static final int PULL_TO_REFRESH = 0x0;
static final int RELEASE_TO_REFRESH = 0x1;
static final int REFRESHING = 0x2;
static final int MANUAL_REFRESHING = 0x3;


public static final int MODE_PULL_DOWN_TO_REFRESH = 0x1;
public static final int MODE_PULL_UP_TO_REFRESH = 0x2;
public static final int MODE_BOTH = 0x3;


// ===========================================================
// Fields
// ===========================================================


private int touchSlop;


private float initialMotionY;
private float lastMotionX;
private float lastMotionY;
private boolean isBeingDragged = false;


private int state = PULL_TO_REFRESH;
private int mode = MODE_PULL_DOWN_TO_REFRESH;
private int currentMode;


private boolean disableScrollingWhileRefreshing = true;


T refreshableView;
private boolean isPullToRefreshEnabled = true;


private LoadingLayout headerLayout;
private LoadingLayout footerLayout;
private int headerHeight;


private final Handler handler = new Handler();


private OnRefreshListener onRefreshListener;


private SmoothScrollRunnable currentSmoothScrollRunnable;


// ===========================================================
// Constructors
// ===========================================================


public PullToRefreshBase(Context context) {
super(context);
init(context, null);
}


public PullToRefreshBase(Context context, int mode) {
super(context);
this.mode = mode;
init(context, null);
}


public PullToRefreshBase(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}


// ===========================================================
// Getter & Setter
// ===========================================================


/**
* Deprecated. Use {@link #getRefreshableView()} from now on.

* @deprecated
* @return The Refreshable View which is currently wrapped
*/
public final T getAdapterView() {
return refreshableView;
}


/**
* Get the Wrapped Refreshable View. Anything returned here has already been
* added to the content view.

* @return The View which is currently wrapped
*/
public final T getRefreshableView() {
return refreshableView;
}


/**
* Whether Pull-to-Refresh is enabled

* @return enabled
*/
public final boolean isPullToRefreshEnabled() {
return isPullToRefreshEnabled;
}


/**
* Returns whether the widget has disabled scrolling on the Refreshable View
* while refreshing.

* @param true if the widget has disabled scrolling while refreshing
*/
public final boolean isDisableScrollingWhileRefreshing() {
return disableScrollingWhileRefreshing;
}


/**
* Returns whether the Widget is currently in the Refreshing state

* @return true if the Widget is currently refreshing
*/
public final boolean isRefreshing() {
return state == REFRESHING || state == MANUAL_REFRESHING;
}


/**
* By default the Widget disabled scrolling on the Refreshable View while
* refreshing. This method can change this behaviour.

* @param disableScrollingWhileRefreshing
*            - true if you want to disable scrolling while refreshing
*/
public final void setDisableScrollingWhileRefreshing(boolean disableScrollingWhileRefreshing) {
this.disableScrollingWhileRefreshing = disableScrollingWhileRefreshing;
}


/**
* Mark the current Refresh as complete. Will Reset the UI and hide the
* Refreshing View
*/
public final void onRefreshComplete() {
if (state != PULL_TO_REFRESH) {
resetHeader();
}
}


/**
* Set OnRefreshListener for the Widget

* @param listener
*            - Listener to be used when the Widget is set to Refresh
*/
public final void setOnRefreshListener(OnRefreshListener listener) {
onRefreshListener = listener;
}


/**
* A mutator to enable/disable Pull-to-Refresh for the current View

* @param enable
*            Whether Pull-To-Refresh should be used
*/
public final void setPullToRefreshEnabled(boolean enable) {
this.isPullToRefreshEnabled = enable;
}


/**
* Set Text to show when the Widget is being pulled, and will refresh when
* released

* @param releaseLabel
*            - String to display
*/
public void setReleaseLabel(String releaseLabel) {
if (null != headerLayout) {
headerLayout.setReleaseLabel(releaseLabel);
}
if (null != footerLayout) {
footerLayout.setReleaseLabel(releaseLabel);
}
}


/**
* Set Text to show when the Widget is being Pulled

* @param pullLabel
*            - String to display
*/
public void setPullLabel(String pullLabel) {
if (null != headerLayout) {
headerLayout.setPullLabel(pullLabel);
}
if (null != footerLayout) {
footerLayout.setPullLabel(pullLabel);
}
}


/**
* Set Text to show when the Widget is refreshing

* @param refreshingLabel
*            - String to display
*/
public void setRefreshingLabel(String refreshingLabel) {
if (null != headerLayout) {
headerLayout.setRefreshingLabel(refreshingLabel);
}
if (null != footerLayout) {
footerLayout.setRefreshingLabel(refreshingLabel);
}
}


public final void setRefreshing() {
this.setRefreshing(true);
}


/**
* Sets the Widget to be in the refresh state. The UI will be updated to
* show the 'Refreshing' view.

* @param doScroll
*            - true if you want to force a scroll to the Refreshing view.
*/
public final void setRefreshing(boolean doScroll) {
if (!isRefreshing()) {
setRefreshingInternal(doScroll);
state = MANUAL_REFRESHING;
}
}


public final boolean hasPullFromTop() {
return currentMode != MODE_PULL_UP_TO_REFRESH;
}


// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================


@Override
public final boolean onTouchEvent(MotionEvent event) {
if (!isPullToRefreshEnabled) {
return false;
}


if (isRefreshing() && disableScrollingWhileRefreshing) {
return true;
}


if (event.getAction() == MotionEvent.ACTION_DOWN && event.getEdgeFlags() != 0) {
return false;
}


switch (event.getAction()) {


case MotionEvent.ACTION_MOVE: {
if (isBeingDragged) {
lastMotionY = event.getY();
this.pullEvent();
return true;
}
break;
}


case MotionEvent.ACTION_DOWN: {
if (isReadyForPull()) {
lastMotionY = initialMotionY = event.getY();
return true;
}
break;
}


case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP: {
if (isBeingDragged) {
isBeingDragged = false;


if (state == RELEASE_TO_REFRESH && null != onRefreshListener) {
setRefreshingInternal(true);
onRefreshListener.onRefresh();
} else {
smoothScrollTo(0);
}
return true;
}
break;
}
}


return false;
}


@Override
public final boolean onInterceptTouchEvent(MotionEvent event) {


if (!isPullToRefreshEnabled) {
return false;
}


if (isRefreshing() && disableScrollingWhileRefreshing) {
return true;
}


final int action = event.getAction();


if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
isBeingDragged = false;
return false;
}


if (action != MotionEvent.ACTION_DOWN && isBeingDragged) {
return true;
}


switch (action) {
case MotionEvent.ACTION_MOVE: {
if (isReadyForPull()) {


final float y = event.getY();
final float dy = y - lastMotionY;
final float yDiff = Math.abs(dy);
final float xDiff = Math.abs(event.getX() - lastMotionX);


if (yDiff > touchSlop && yDiff > xDiff) {
if ((mode == MODE_PULL_DOWN_TO_REFRESH || mode == MODE_BOTH) && dy >= 0.0001f
&& isReadyForPullDown()) {
lastMotionY = y;
isBeingDragged = true;
if (mode == MODE_BOTH) {
currentMode = MODE_PULL_DOWN_TO_REFRESH;
}
} else if ((mode == MODE_PULL_UP_TO_REFRESH || mode == MODE_BOTH) && dy <= 0.0001f
&& isReadyForPullUp()) {
lastMotionY = y;
isBeingDragged = true;
if (mode == MODE_BOTH) {
currentMode = MODE_PULL_UP_TO_REFRESH;
}
}
}
}
break;
}
case MotionEvent.ACTION_DOWN: {
if (isReadyForPull()) {
lastMotionY = initialMotionY = event.getY();
lastMotionX = event.getX();
isBeingDragged = false;
}
break;
}
}


return isBeingDragged;
}


protected void addRefreshableView(Context context, T refreshableView) {
addView(refreshableView, new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, 0, 1.0f));
}


/**
* This is implemented by derived classes to return the created View. If you
* need to use a custom View (such as a custom ListView), override this
* method and return an instance of your custom class.

* Be sure to set the ID of the view in this method, especially if you're
* using a ListActivity or ListFragment.

* @param context
* @param attrs
*            AttributeSet from wrapped class. Means that anything you
*            include in the XML layout declaration will be routed to the
*            created View
* @return New instance of the Refreshable View
*/
protected abstract T createRefreshableView(Context context, AttributeSet attrs);


protected final int getCurrentMode() {
return currentMode;
}


protected final LoadingLayout getFooterLayout() {
return footerLayout;
}


protected final LoadingLayout getHeaderLayout() {
return headerLayout;
}


protected final int getHeaderHeight() {
return headerHeight;
}


protected final int getMode() {
return mode;
}


/**
* Implemented by derived class to return whether the View is in a state
* where the user can Pull to Refresh by scrolling down.

* @return true if the View is currently the correct state (for example, top
*         of a ListView)
*/
protected abstract boolean isReadyForPullDown();


/**
* Implemented by derived class to return whether the View is in a state
* where the user can Pull to Refresh by scrolling up.

* @return true if the View is currently in the correct state (for example,
*         bottom of a ListView)
*/
protected abstract boolean isReadyForPullUp();


// ===========================================================
// Methods
// ===========================================================


protected void resetHeader() {
state = PULL_TO_REFRESH;
isBeingDragged = false;


if (null != headerLayout) {
headerLayout.reset();
}
if (null != footerLayout) {
footerLayout.reset();
}


smoothScrollTo(0);
}


protected void setRefreshingInternal(boolean doScroll) {
state = REFRESHING;


if (null != headerLayout) {
headerLayout.refreshing();
}
if (null != footerLayout) {
footerLayout.refreshing();
}


if (doScroll) {
smoothScrollTo(currentMode == MODE_PULL_DOWN_TO_REFRESH ? -headerHeight : headerHeight);
}
}


protected final void setHeaderScroll(int y) {
scrollTo(0, y);
}


protected final void smoothScrollTo(int y) {
if (null != currentSmoothScrollRunnable) {
currentSmoothScrollRunnable.stop();
}


if (this.getScrollY() != y) {
this.currentSmoothScrollRunnable = new SmoothScrollRunnable(handler, getScrollY(), y);
handler.post(currentSmoothScrollRunnable);
}
}


private void init(Context context, AttributeSet attrs) {


setOrientation(LinearLayout.VERTICAL);


touchSlop = ViewConfiguration.getTouchSlop();


// Styleables from XML
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PullToRefresh);
if (a.hasValue(R.styleable.PullToRefresh_mode)) {
mode = a.getInteger(R.styleable.PullToRefresh_mode, MODE_PULL_DOWN_TO_REFRESH);
}


// Refreshable View
// By passing the attrs, we can add ListView/GridView params via XML
refreshableView = this.createRefreshableView(context, attrs);
this.addRefreshableView(context, refreshableView);


// Loading View Strings
String pullLabel = context.getString(R.string.pull_to_refresh_pull_label);
String refreshingLabel = context.getString(R.string.pull_to_refresh_refreshing_label);
String releaseLabel = context.getString(R.string.pull_to_refresh_release_label);


// Add Loading Views
if (mode == MODE_PULL_DOWN_TO_REFRESH || mode == MODE_BOTH) {
headerLayout = new LoadingLayout(context, MODE_PULL_DOWN_TO_REFRESH, releaseLabel, pullLabel,
refreshingLabel);
addView(headerLayout, 0, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
measureView(headerLayout);
headerHeight = headerLayout.getMeasuredHeight();
}
if (mode == MODE_PULL_UP_TO_REFRESH || mode == MODE_BOTH) {
footerLayout = new LoadingLayout(context, MODE_PULL_UP_TO_REFRESH, releaseLabel, pullLabel, refreshingLabel);
addView(footerLayout, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
measureView(footerLayout);
headerHeight = footerLayout.getMeasuredHeight();
}


// Styleables from XML
if (a.hasValue(R.styleable.PullToRefresh_headerTextColor)) {
final int color = a.getColor(R.styleable.PullToRefresh_headerTextColor, Color.BLACK);
if (null != headerLayout) {
headerLayout.setTextColor(color);
}
if (null != footerLayout) {
footerLayout.setTextColor(color);
}
}
if (a.hasValue(R.styleable.PullToRefresh_headerBackground)) {
this.setBackgroundResource(a.getResourceId(R.styleable.PullToRefresh_headerBackground, Color.WHITE));
}
if (a.hasValue(R.styleable.PullToRefresh_adapterViewBackground)) {
refreshableView.setBackgroundResource(a.getResourceId(R.styleable.PullToRefresh_adapterViewBackground,
Color.WHITE));
}
a.recycle();


// Hide Loading Views
switch (mode) {
case MODE_BOTH:
setPadding(0, -headerHeight, 0, -headerHeight);
break;
case MODE_PULL_UP_TO_REFRESH:
setPadding(0, 0, 0, -headerHeight);
break;
case MODE_PULL_DOWN_TO_REFRESH:
default:
setPadding(0, -headerHeight, 0, 0);
break;
}


// If we're not using MODE_BOTH, then just set currentMode to current
// mode
if (mode != MODE_BOTH) {
currentMode = mode;
}
}


private void measureView(View child) {
ViewGroup.LayoutParams p = child.getLayoutParams();
if (p == null) {
p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_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);
}


/**
* Actions a Pull Event

* @return true if the Event has been handled, false if there has been no
*         change
*/
private boolean pullEvent() {


final int newHeight;
final int oldHeight = this.getScrollY();


switch (currentMode) {
case MODE_PULL_UP_TO_REFRESH:
newHeight = Math.round(Math.max(initialMotionY - lastMotionY, 0) / FRICTION);
// newHeight = Math.round((initialMotionY - lastMotionY) / FRICTION);
break;
case MODE_PULL_DOWN_TO_REFRESH:
default:
newHeight = Math.round(Math.min(initialMotionY - lastMotionY, 0) / FRICTION);
// newHeight = Math.round((initialMotionY - lastMotionY) / FRICTION);
break;
}


setHeaderScroll(newHeight);


if (newHeight != 0) {
if (state == PULL_TO_REFRESH && headerHeight < Math.abs(newHeight)) {
state = RELEASE_TO_REFRESH;


switch (currentMode) {
case MODE_PULL_UP_TO_REFRESH:
footerLayout.releaseToRefresh();
break;
case MODE_PULL_DOWN_TO_REFRESH:
headerLayout.releaseToRefresh();
break;
}


return true;


} else if (state == RELEASE_TO_REFRESH && headerHeight >= Math.abs(newHeight)) {
state = PULL_TO_REFRESH;


switch (currentMode) {
case MODE_PULL_UP_TO_REFRESH:
footerLayout.pullToRefresh();
break;
case MODE_PULL_DOWN_TO_REFRESH:
headerLayout.pullToRefresh();
break;
}


return true;
}
}


return oldHeight != newHeight;
}


private boolean isReadyForPull() {
switch (mode) {
case MODE_PULL_DOWN_TO_REFRESH:
return isReadyForPullDown();
case MODE_PULL_UP_TO_REFRESH:
return isReadyForPullUp();
case MODE_BOTH:
return isReadyForPullUp() || isReadyForPullDown();
}
return false;
}


// ===========================================================
// Inner and Anonymous Classes
// ===========================================================


public static interface OnRefreshListener {


public void onRefresh();


}


public static interface OnLastItemVisibleListener {


public void onLastItemVisible();


}


@Override
public void setLongClickable(boolean longClickable) {
getRefreshableView().setLongClickable(longClickable);
}
}



package com.stay.pull.lib;


import android.content.Context;
import android.util.AttributeSet;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View;
import android.widget.ListView;


import com.stay.pull.lib.internal.EmptyViewMethodAccessor;


public class PullToRefreshListView extends PullToRefreshAdapterViewBase<ListView> {
                                                  
// private LoadingLayout headerLoadingView;
// private LoadingLayout footerLoadingView;


class InternalListView extends ListView implements EmptyViewMethodAccessor {

public InternalListView(Context context, AttributeSet attrs) {
super(context, attrs);
}


@Override
public void setEmptyView(View emptyView) {
PullToRefreshListView.this.setEmptyView(emptyView);
}

@Override
public void setEmptyViewInternal(View emptyView) {
super.setEmptyView(emptyView);
}


public ContextMenuInfo getContextMenuInfo() {
return super.getContextMenuInfo();
}
}


public PullToRefreshListView(Context context) {
super(context);
this.setDisableScrollingWhileRefreshing(false);
}

public PullToRefreshListView(Context context, int mode) {
super(context, mode);
this.setDisableScrollingWhileRefreshing(false);
}


public PullToRefreshListView(Context context, AttributeSet attrs) {
super(context, attrs);
this.setDisableScrollingWhileRefreshing(false);
}


@Override
public ContextMenuInfo getContextMenuInfo() {
return ((InternalListView) getRefreshableView()).getContextMenuInfo();
}


// public void setReleaseLabel(String releaseLabel) {
// super.setReleaseLabel(releaseLabel);
// if (null != headerLoadingView) {
// headerLoadingView.setReleaseLabel(releaseLabel);
// }
// if (null != footerLoadingView) {
// footerLoadingView.setReleaseLabel(releaseLabel);
// }
// }
//
// public void setPullLabel(String pullLabel) {
// super.setPullLabel(pullLabel);
//
// if (null != headerLoadingView) {
// headerLoadingView.setPullLabel(pullLabel);
// }
// if (null != footerLoadingView) {
// footerLoadingView.setPullLabel(pullLabel);
// }
// }
//
// public void setRefreshingLabel(String refreshingLabel) {
// super.setRefreshingLabel(refreshingLabel);
//
// if (null != headerLoadingView) {
// headerLoadingView.setRefreshingLabel(refreshingLabel);
// }
// if (null != footerLoadingView) {
// footerLoadingView.setRefreshingLabel(refreshingLabel);
// }
// }


@Override
protected final ListView createRefreshableView(Context context, AttributeSet attrs) {
ListView lv = new InternalListView(context, attrs);
// final int mode = this.getMode();
//
// // Loading View Strings
// String pullLabel = context.getString(R.string.pull_to_refresh_pull_label);
// String refreshingLabel = context.getString(R.string.pull_to_refresh_refreshing_label);
// String releaseLabel = context.getString(R.string.pull_to_refresh_release_label);


// Add Loading Views
// if (mode == MODE_PULL_DOWN_TO_REFRESH || mode == MODE_BOTH) {
// FrameLayout frame = new FrameLayout(context);
// headerLoadingView = new LoadingLayout(context, MODE_PULL_DOWN_TO_REFRESH, releaseLabel, pullLabel,
// refreshingLabel);
// frame.addView(headerLoadingView, FrameLayout.LayoutParams.FILL_PARENT,
// FrameLayout.LayoutParams.WRAP_CONTENT);
// headerLoadingView.setVisibility(View.GONE);
// lv.addHeaderView(frame);
// }
// if (mode == MODE_PULL_UP_TO_REFRESH || mode == MODE_BOTH) {
// FrameLayout frame = new FrameLayout(context);
// footerLoadingView = new LoadingLayout(context, MODE_PULL_UP_TO_REFRESH, releaseLabel, pullLabel,
// refreshingLabel);
// frame.addView(footerLoadingView, FrameLayout.LayoutParams.FILL_PARENT,
// FrameLayout.LayoutParams.WRAP_CONTENT);
// footerLoadingView.setVisibility(View.GONE);
// lv.addFooterView(frame);
// }


// Set it to this so it can be used in ListActivity/ListFragment
lv.setId(android.R.id.list);
return lv;
}


// @Override
// protected void setRefreshingInternal(boolean doScroll) {
// super.setRefreshingInternal(false);
//
// final LoadingLayout originalLoadingLayout, listViewLoadingLayout;
// final int selection, scrollToY;
//
// switch (getCurrentMode()) {
// case MODE_PULL_UP_TO_REFRESH:
// originalLoadingLayout = this.getFooterLayout();
// listViewLoadingLayout = this.footerLoadingView;
// selection = refreshableView.getCount() - 1;
// scrollToY = getScrollY() - getHeaderHeight();
// break;
// case MODE_PULL_DOWN_TO_REFRESH:
// default:
// originalLoadingLayout = this.getHeaderLayout();
// listViewLoadingLayout = this.headerLoadingView;
// selection = 0;
// scrollToY = getScrollY() + getHeaderHeight();
// break;
// }
//
// if (doScroll) {
// // We scroll slightly so that the ListView's header/footer is at the
// // same Y position as our normal header/footer
// this.setHeaderScroll(scrollToY);
// }
//
// // Hide our original Loading View
// originalLoadingLayout.setVisibility(View.INVISIBLE);
//
// // Show the ListView Loading View and set it to refresh
// listViewLoadingLayout.setVisibility(View.VISIBLE);
// listViewLoadingLayout.refreshing();
//
// if (doScroll) {
// // Make sure the ListView is scrolled to show the loading
// // header/footer
// refreshableView.setSelection(selection);
//
// // Smooth scroll as normal
// smoothScrollTo(0);
// }
// }


// @Override
// protected void resetHeader() {
//
// LoadingLayout originalLoadingLayout;
// LoadingLayout listViewLoadingLayout;
//
// int scrollToHeight = getHeaderHeight();
// final boolean doScroll;
//
// switch (getCurrentMode()) {
// case MODE_PULL_UP_TO_REFRESH:
// originalLoadingLayout = this.getFooterLayout();
// listViewLoadingLayout = footerLoadingView;
// doScroll = this.isReadyForPullUp();
// break;
// case MODE_PULL_DOWN_TO_REFRESH:
// default:
// originalLoadingLayout = this.getHeaderLayout();
// listViewLoadingLayout = headerLoadingView;
// scrollToHeight *= -1;
// doScroll = this.isReadyForPullDown();
// break;
// }
//
// // Set our Original View to Visible
// originalLoadingLayout.setVisibility(View.VISIBLE);
//
// // Scroll so our View is at the same Y as the ListView header/footer,
// // but only scroll if the ListView is at the top/bottom
// if (doScroll) {
// this.setHeaderScroll(scrollToHeight);
// }
//
// // Hide the ListView Header/Footer
// listViewLoadingLayout.setVisibility(View.GONE);
//
// super.resetHeader();
// }


}


package com.stay.pull.lib.internal;


import android.view.View;
import android.widget.ImageView;


/**
 * Interface that allows PullToRefreshBase to hijack the call to
 * AdapterView.setEmptyView()
 * 
 * @author chris
 */
public interface EmptyViewMethodAccessor {


/**
* Calls upto AdapterView.setEmptyView()

* @param View
*            to set as Empty View
*/
public void setEmptyViewInternal(View emptyView);


/**
* Should call PullToRefreshBase.setEmptyView() which will then
* automatically call through to setEmptyViewInternal()

* @param View
*            to set as Empty View
*/
public void setEmptyView(View emptyView);




}


package com.stay.pull.lib.internal;


import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;


import com.stay.pull.R;
import com.stay.pull.lib.PullToRefreshBase;


public class LoadingLayout extends FrameLayout {


static final int DEFAULT_ROTATION_ANIMATION_DURATION = 150;


private final ImageView headerImage;
private final ProgressBar headerProgress;
private final TextView headerText;


private String pullLabel;
private String refreshingLabel;
private String releaseLabel;


private final Animation rotateAnimation, resetRotateAnimation;


public LoadingLayout(Context context, final int mode, String releaseLabel, String pullLabel, String refreshingLabel) {
super(context);
ViewGroup header = (ViewGroup) LayoutInflater.from(context).inflate(R.layout.pull_to_refresh_header, this);
headerText = (TextView) header.findViewById(R.id.pull_to_refresh_text);
headerImage = (ImageView) header.findViewById(R.id.pull_to_refresh_image);
headerProgress = (ProgressBar) header.findViewById(R.id.pull_to_refresh_progress);


final Interpolator interpolator = new LinearInterpolator();
rotateAnimation = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
       0.5f);
rotateAnimation.setInterpolator(interpolator);
rotateAnimation.setDuration(DEFAULT_ROTATION_ANIMATION_DURATION);
rotateAnimation.setFillAfter(true);


resetRotateAnimation = new RotateAnimation(-180, 0, Animation.RELATIVE_TO_SELF, 0.5f,
       Animation.RELATIVE_TO_SELF, 0.5f);
resetRotateAnimation.setInterpolator(interpolator);
resetRotateAnimation.setDuration(DEFAULT_ROTATION_ANIMATION_DURATION);
resetRotateAnimation.setFillAfter(true);


this.releaseLabel = releaseLabel;
this.pullLabel = pullLabel;
this.refreshingLabel = refreshingLabel;


switch (mode) {
case PullToRefreshBase.MODE_PULL_UP_TO_REFRESH:
headerImage.setImageResource(R.drawable.pulltorefresh_up_arrow);
break;
case PullToRefreshBase.MODE_PULL_DOWN_TO_REFRESH:
default:
headerImage.setImageResource(R.drawable.pulltorefresh_down_arrow);
break;
}
}


public void reset() {
headerText.setText(pullLabel);
headerImage.setVisibility(View.VISIBLE);
headerProgress.setVisibility(View.GONE);
}


public void releaseToRefresh() {
headerText.setText(releaseLabel);
headerImage.clearAnimation();
headerImage.startAnimation(rotateAnimation);
}


public void setPullLabel(String pullLabel) {
this.pullLabel = pullLabel;
}


public void refreshing() {
headerText.setText(refreshingLabel);
headerImage.clearAnimation();
headerImage.setVisibility(View.INVISIBLE);
headerProgress.setVisibility(View.VISIBLE);
}


public void setRefreshingLabel(String refreshingLabel) {
this.refreshingLabel = refreshingLabel;
}


public void setReleaseLabel(String releaseLabel) {
this.releaseLabel = releaseLabel;
}


public void pullToRefresh() {
headerText.setText(pullLabel);
headerImage.clearAnimation();
headerImage.startAnimation(resetRotateAnimation);
}


public void setTextColor(int color) {
headerText.setTextColor(color);
}


}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章