你的位置:首页 > 操作系统

[操作系统]下拉刷新和返回顶部


如下是布局文件 主要是一个PullToRefreshView内包含一个Scrollview   在滑动面中放一个GridView  底部放个按钮 当点击时会返回手机顶部

其中的滑动PullToRefreshView是我从别人的代码直接拿来的

<?  android:layout_width="match_parent"  android:layout_height="match_parent"  android:background="#eee"  android:orientation="vertical" >  <TextView    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:layout_marginLeft="15dp"    android:gravity="center_vertical"    android:paddingBottom="4dp"    android:paddingTop="5dp"    android:text="所有产品"    android:textSize="15sp" />  <View    android:layout_width="fill_parent"    android:layout_height="1dp"    android:background="@android:color/white" />  <org.="@+id/pulltorefresh"    android:layout_width="match_parent"    android:layout_height="wrap_content" >    <ScrollView      android:id="@+id/sc_view_id"      android:layout_width="match_parent"      android:layout_height="wrap_content" >      <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="vertical" >        <org.="@+id/product"          android:layout_width="match_parent"          android:layout_height="wrap_content"          android:horizontalSpacing="5dp"          android:numColumns="2"          android:paddingBottom="10dp"          android:paddingLeft="7dp"          android:paddingRight="7dp"          android:paddingTop="5dp"          android:verticalSpacing="8dp" />        <LinearLayout          android:layout_width="match_parent"          android:layout_height="50dp"          android:layout_marginTop="10dp"          android:background="@android:color/white"          android:orientation="horizontal"          android:padding="5dp" >          <TextView            android:id="@+id/tv_backtop"            android:layout_width="match_parent"            android:layout_height="match_parent"            android:drawableRight="@drawable/back_top"            android:gravity="center"            android:text="点击 将返回顶部"            android:paddingRight="10dp"            android:textColor="@android:color/black"            android:textSize="14sp" />        </LinearLayout>      </LinearLayout>    </ScrollView>  </org.

主代码是

package org.import java.text.DateFormat;import java.util.Date;import org.import org.import ogg.huanxin.huadong.R;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.view.Window;import android.widget.AdapterView;import android.widget.TextView;import android.widget.AdapterView.OnItemClickListener;public class MyProducte extends Activity implements OnHeaderRefreshListener, OnFooterRefreshListener {  // private GridView productGridView;  /** 定义产品 */  private MyGridView product_gridView;  /** 产品的适配器 */  private ProducteGridAdapter producteGridAdapter;  /** 下拉刷新 */  private PullToRefreshView pullToRefreshView;  /** 点击返回到顶部 */  private TextView tv_backtop;  @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    //取消标题栏    requestWindowFeature(Window.FEATURE_NO_TITLE);    // 定义布局变量    super.setContentView(R.layout.home_product);        pullToRefreshView = (PullToRefreshView) super        .findViewById(R.id.pulltorefresh);    //头部刷新    pullToRefreshView.setOnHeaderRefreshListener(this);    //尾部刷新    pullToRefreshView.setOnFooterRefreshListener(this);        pullToRefreshView.setLastUpdated(new Date().toLocaleString());        // 取得控件    product_gridView = (MyGridView) super.findViewById(R.id.product);    tv_backtop = (TextView) super.findViewById(R.id.tv_backtop);    // 设置适配器    producteGridAdapter = new ProducteGridAdapter(this);    product_gridView.setAdapter(producteGridAdapter);    // product_gridView.setOnItemClickListener(new ItemClickListener());    product_gridView.setOnItemClickListener(new ItemClickListener());    // tv_backtop的监听器    tv_backtop.setOnClickListener(new android.view.View.OnClickListener() {      @Override      public void onClick(View arg0) {        // TODO Auto-generated method stub        product_gridView.post(new Runnable() {          @Override          public void run() {            // TODO Auto-generated method stub            MyProducte.this.findViewById(R.id.sc_view_id).scrollTo(                0, 0);          }        });      }    });  }  private class ItemClickListener implements OnItemClickListener {    @Override    public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,        long arg3) {      // TODO Auto-generated method stub    }  }  @Override  public void onHeaderRefresh(PullToRefreshView view) {    // TODO Auto-generated method stub    pullToRefreshView.postDelayed(new Runnable() {      @Override      public void run() {        // TODO Auto-generated method stub        Date date = new Date();        DateFormat ddf = DateFormat.getDateInstance();        String day = ddf.format(date);        DateFormat ddy = DateFormat.getTimeInstance();        String timeString = ddy.format(date);        DateFormat ddty = DateFormat.getDateTimeInstance();        String shjian = ddty.format(date);        System.out.println(day + "----" + timeString + "--------"            + shjian);        // pullToRefreshView.onHeaderRefreshComplete("更新为"+new        // Date().toLocaleString());        pullToRefreshView.onHeaderRefreshComplete("更新为" + timeString);      }    }, 1000);  }  @Override  public void onFooterRefresh(PullToRefreshView view) {    // TODO Auto-generated method stub    pullToRefreshView.onFooterRefreshComplete();  }}

其中的PullToRefreshView的代码是也是别人的全代码

package org.import ogg.huanxin.huadong.R;import android.content.Context;import android.util.AttributeSet;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.AdapterView;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.ProgressBar;import android.widget.ScrollView;import android.widget.TextView;public class PullToRefreshView extends LinearLayout {  // private static final String TAG = "PullToRefreshView";  // refresh states  private static final int PULL_TO_REFRESH = 2;  private static final int RELEASE_TO_REFRESH = 3;  private static final int REFRESHING = 4;  // pull state  private static final int PULL_UP_STATE = 0;  private static final int PULL_DOWN_STATE = 1;  /**   * last y   */  private int mLastMotionY;  /**   * lock   */  // private boolean mLock;  /**   * header view   */  private View mHeaderView;  /**   * footer view   */  private View mFooterView;  /**   * list or grid   */  private AdapterView<?> mAdapterView;  /**   * scrollview   */  private ScrollView mScrollView;  /**   * header view height   */  private int mHeaderViewHeight;  /**   * footer view height   */  private int mFooterViewHeight;  /**   * header view image   */  private ImageView mHeaderImageView;  /**   * footer view image   */  private ImageView mFooterImageView;  /**   * header tip text   */  private TextView mHeaderTextView;  /**   * footer tip text   */  private TextView mFooterTextView;  /**   * header refresh time   */  private TextView mHeaderUpdateTextView;  /**   * footer refresh time   */  // private TextView mFooterUpdateTextView;  /**   * header progress bar   */  private ProgressBar mHeaderProgressBar;  /**   * footer progress bar   */  private ProgressBar mFooterProgressBar;  /**   * layout inflater   */  private LayoutInflater mInflater;  /**   * header view current state   */  private int mHeaderState;  /**   * footer view current state   */  private int mFooterState;  /**   * pull state,pull up or pull down;PULL_UP_STATE or PULL_DOWN_STATE   */  private int mPullState;  /**   * 变为向下的箭头,改变箭头方向   */  private RotateAnimation mFlipAnimation;  /**   * 变为逆向的箭头,旋转   */  private RotateAnimation mReverseFlipAnimation;  /**   * footer refresh listener   */  private OnFooterRefreshListener mOnFooterRefreshListener;  /**   * footer refresh listener   */  private OnHeaderRefreshListener mOnHeaderRefreshListener;  /**   * last update time   */  // private String mLastUpdateTime;  public PullToRefreshView(Context context, AttributeSet attrs) {    super(context, attrs);    init();  }  public PullToRefreshView(Context context) {    super(context);    init();  }  /**   * init   *   * @param context   */  private void init() {    // 需要设置成vertical    setOrientation(LinearLayout.VERTICAL);    // Load all of the animations we need in code rather than through     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.from(getContext());    // header view 在此添加,保证是第一个添加到linearlayout的最上端    addHeaderView();  }  private void addHeaderView() {    // header view    mHeaderView = mInflater.inflate(R.layout.refresh_header, this, false);    mHeaderImageView = (ImageView) mHeaderView        .findViewById(R.id.pull_to_refresh_image);    mHeaderTextView = (TextView) mHeaderView        .findViewById(R.id.pull_to_refresh_text);    mHeaderUpdateTextView = (TextView) mHeaderView        .findViewById(R.id.pull_to_refresh_updated_at);    mHeaderProgressBar = (ProgressBar) mHeaderView        .findViewById(R.id.pull_to_refresh_progress);    // header layout    measureView(mHeaderView);    mHeaderViewHeight = mHeaderView.getMeasuredHeight();    LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,        mHeaderViewHeight);    // 设置topMargin的值为负的header View高度,即将其隐藏在最上方    params.topMargin = -(mHeaderViewHeight);    // mHeaderView.setLayoutParams(params1);    addView(mHeaderView, params);  }  private void addFooterView() {    // footer view    mFooterView = mInflater.inflate(R.layout.refresh_footer, this, false);    mFooterImageView = (ImageView) mFooterView        .findViewById(R.id.pull_to_load_image);    mFooterTextView = (TextView) mFooterView        .findViewById(R.id.pull_to_load_text);    mFooterProgressBar = (ProgressBar) mFooterView        .findViewById(R.id.pull_to_load_progress);    // footer layout    measureView(mFooterView);    mFooterViewHeight = mFooterView.getMeasuredHeight();    LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,        mFooterViewHeight);    // int top = getHeight();    // params.topMargin    // =getHeight();//在这里getHeight()==0,但在onInterceptTouchEvent()方法里getHeight()已经有值了,不再是0;    // getHeight()什么时候会赋值,稍候再研究一下    // 由于是线性布局可以直接添加,只要AdapterView的高度是MATCH_PARENT,那么footer view就会被添加到最后,并隐藏    addView(mFooterView, params);  }  @Override  protected void onFinishInflate() {    super.onFinishInflate();    // footer view 在此添加保证添加到linearlayout中的最后    addFooterView();    initContentAdapterView();  }  /**   * init AdapterView like ListView,GridView and so on;or init ScrollView   *   */  private void initContentAdapterView() {    int count = getChildCount();    if (count < 3) {      throw new IllegalArgumentException(          "This layout must contain 3 child views,and AdapterView or ScrollView must in the second position!");    }    View view = null;    for (int i = 0; i < count - 1; ++i) {      view = getChildAt(i);      if (view instanceof AdapterView<?>) {        mAdapterView = (AdapterView<?>) view;      }      if (view instanceof ScrollView) {        // finish later        mScrollView = (ScrollView) view;      }    }    if (mAdapterView == null && mScrollView == null) {      throw new IllegalArgumentException(          "must contain a AdapterView or ScrollView in this layout!");    }  }  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 boolean onInterceptTouchEvent(MotionEvent e) {    int y = (int) e.getRawY();    switch (e.getAction()) {    case MotionEvent.ACTION_DOWN:      // 首先拦截down事件,记录y坐标      mLastMotionY = y;      break;    case MotionEvent.ACTION_MOVE:      // deltaY > 0 是向下运动,< 0是向上运动      int deltaY = y - mLastMotionY;      if (isRefreshViewScroll(deltaY)) {        return true;      }      break;    case MotionEvent.ACTION_UP:    case MotionEvent.ACTION_CANCEL:      break;    }    return false;  }  /*   * 如果在onInterceptTouchEvent()方法中没有拦截(即onInterceptTouchEvent()方法中 return   * false)则由PullToRefreshView 的子View来处理;否则由下面的方法来处理(即由PullToRefreshView自己来处理)   */  @Override  public boolean onTouchEvent(MotionEvent event) {    // if (mLock) {    // return true;    // }    int y = (int) event.getRawY();    switch (event.getAction()) {    case MotionEvent.ACTION_DOWN:      // onInterceptTouchEvent已经记录      // mLastMotionY = y;      break;    case MotionEvent.ACTION_MOVE:      int deltaY = y - mLastMotionY;      if (mPullState == PULL_DOWN_STATE) {// 执行下拉        headerPrepareToRefresh(deltaY);        // setHeaderPadding(-mHeaderViewHeight);      } else if (mPullState == PULL_UP_STATE) {// 执行上拉        footerPrepareToRefresh(deltaY);      }      mLastMotionY = y;      break;    case MotionEvent.ACTION_UP:    case MotionEvent.ACTION_CANCEL:      int topMargin = getHeaderTopMargin();      if (mPullState == PULL_DOWN_STATE) {        if (topMargin >= 0) {          // 开始刷新          headerRefreshing();        } else {          // 还没有执行刷新,重新隐藏          setHeaderTopMargin(-mHeaderViewHeight);        }      } else if (mPullState == PULL_UP_STATE) {        if (Math.abs(topMargin) >= mHeaderViewHeight            + mFooterViewHeight) {          // 开始执行footer 刷新          footerRefreshing();        } else {          // 还没有执行刷新,重新隐藏          setHeaderTopMargin(-mHeaderViewHeight);        }      }      break;    }    return super.onTouchEvent(event);  }  /**   * 是否应该到了父View,即PullToRefreshView滑动   *   * @param deltaY   *      , deltaY > 0 是向下运动,< 0是向上运动   * @return   */  private boolean isRefreshViewScroll(int deltaY) {    if (mHeaderState == REFRESHING || mFooterState == REFRESHING) {      return false;    }    // 对于ListView和GridView    if (mAdapterView != null) {      // 子view(ListView or GridView)滑动到最顶端      if (deltaY > 0) {        View child = mAdapterView.getChildAt(0);        if (child == null) {          // 如果mAdapterView中没有数据,不拦截          return false;        }        if (mAdapterView.getFirstVisiblePosition() == 0            && child.getTop() == 0) {          mPullState = PULL_DOWN_STATE;          return true;        }        int top = child.getTop();        int padding = mAdapterView.getPaddingTop();        if (mAdapterView.getFirstVisiblePosition() == 0            && Math.abs(top - padding) <= 8) {// 这里之前用3可以判断,但现在不行,还没找到原因          mPullState = PULL_DOWN_STATE;          return true;        }      } else if (deltaY < 0) {        View lastChild = mAdapterView.getChildAt(mAdapterView            .getChildCount() - 1);        if (lastChild == null) {          // 如果mAdapterView中没有数据,不拦截          return false;        }        // 最后一个子view的Bottom小于父View的高度说明mAdapterView的数据没有填满父view,        // 等于父View的高度说明mAdapterView已经滑动到最后        if (lastChild.getBottom() <= getHeight()            && mAdapterView.getLastVisiblePosition() == mAdapterView                .getCount() - 1) {          mPullState = PULL_UP_STATE;          return true;        }      }    }    // 对于ScrollView    if (mScrollView != null) {      // 子scroll view滑动到最顶端      View child = mScrollView.getChildAt(0);      if (deltaY > 0 && mScrollView.getScrollY() == 0) {        mPullState = PULL_DOWN_STATE;        return true;      } else if (deltaY < 0          && child.getMeasuredHeight() <= getHeight()              + mScrollView.getScrollY()) {        mPullState = PULL_UP_STATE;        return true;      }    }    return false;  }  /**   * header 准备刷新,手指移动过程,还没有释放   *   * @param deltaY   *      ,手指滑动的距离   */  private void headerPrepareToRefresh(int deltaY) {    int newTopMargin = changingHeaderViewTopMargin(deltaY);    // 当header view的topMargin>=0时,说明已经完全显示出来了,修改header view 的提示状态    if (newTopMargin >= 0 && mHeaderState != RELEASE_TO_REFRESH) {      mHeaderTextView.setText(R.string.app_name);      mHeaderUpdateTextView.setVisibility(View.VISIBLE);      mHeaderImageView.clearAnimation();      mHeaderImageView.startAnimation(mFlipAnimation);      mHeaderState = RELEASE_TO_REFRESH;    } else if (newTopMargin < 0 && newTopMargin > -mHeaderViewHeight) {// 拖动时没有释放      mHeaderImageView.clearAnimation();      mHeaderImageView.startAnimation(mFlipAnimation);      // mHeaderImageView.      mHeaderTextView.setText(R.string.app_name);      mHeaderState = PULL_TO_REFRESH;    }  }  /**   * footer 准备刷新,手指移动过程,还没有释放 移动footer view高度同样和移动header view   * 高度是一样,都是通过修改header view的topmargin的值来达到   *   * @param deltaY   *      ,手指滑动的距离   */  private void footerPrepareToRefresh(int deltaY) {    int newTopMargin = changingHeaderViewTopMargin(deltaY);    // 如果header view topMargin 的绝对值大于或等于header + footer 的高度    // 说明footer view 完全显示出来了,修改footer view 的提示状态    if (Math.abs(newTopMargin) >= (mHeaderViewHeight + mFooterViewHeight)        && mFooterState != RELEASE_TO_REFRESH) {      mFooterTextView          .setText(R.string.app_name);      mFooterImageView.clearAnimation();      mFooterImageView.startAnimation(mFlipAnimation);      mFooterState = RELEASE_TO_REFRESH;    } else if (Math.abs(newTopMargin) < (mHeaderViewHeight + mFooterViewHeight)) {      mFooterImageView.clearAnimation();      mFooterImageView.startAnimation(mFlipAnimation);      mFooterTextView.setText(R.string.app_name);      mFooterState = PULL_TO_REFRESH;    }  }  /**   * 修改Header view top margin的值   *   * @param deltaY   */  private int changingHeaderViewTopMargin(int deltaY) {    LayoutParams params = (LayoutParams) mHeaderView.getLayoutParams();    float newTopMargin = params.topMargin + deltaY * 0.3f;    // 这里对上拉做一下限制,因为当前上拉后然后不释放手指直接下拉,会把下拉刷新给触发了,感谢网友yufengzungzhe的指出    // 表示如果是在上拉后一段距离,然后直接下拉    if (deltaY > 0 && mPullState == PULL_UP_STATE        && Math.abs(params.topMargin) <= mHeaderViewHeight) {      return params.topMargin;    }    // 同样地,对下拉做一下限制,避免出现跟上拉操作时一样的bug    if (deltaY < 0 && mPullState == PULL_DOWN_STATE        && Math.abs(params.topMargin) >= mHeaderViewHeight) {      return params.topMargin;    }    params.topMargin = (int) newTopMargin;    mHeaderView.setLayoutParams(params);    invalidate();    return params.topMargin;  }  /**   * header refreshing   *   */  private void headerRefreshing() {    mHeaderState = REFRESHING;    setHeaderTopMargin(0);    mHeaderImageView.setVisibility(View.GONE);    mHeaderImageView.clearAnimation();    mHeaderImageView.setImageDrawable(null);    mHeaderProgressBar.setVisibility(View.VISIBLE);    mHeaderTextView.setText(R.string.app_name);    if (mOnHeaderRefreshListener != null) {      mOnHeaderRefreshListener.onHeaderRefresh(this);    }  }  /**   * footer refreshing   *   */  private void footerRefreshing() {    mFooterState = REFRESHING;    int top = mHeaderViewHeight + mFooterViewHeight;    setHeaderTopMargin(-top);    mFooterImageView.setVisibility(View.GONE);    mFooterImageView.clearAnimation();    mFooterImageView.setImageDrawable(null);    mFooterProgressBar.setVisibility(View.VISIBLE);    mFooterTextView        .setText(R.string.app_name);    if (mOnFooterRefreshListener != null) {      mOnFooterRefreshListener.onFooterRefresh(this);    }  }  /**   * 设置header view 的topMargin的值   *   * @param topMargin   *      ,为0时,说明header view 刚好完全显示出来; 为-mHeaderViewHeight时,说明完全隐藏了   */  private void setHeaderTopMargin(int topMargin) {    LayoutParams params = (LayoutParams) mHeaderView.getLayoutParams();    params.topMargin = topMargin;    mHeaderView.setLayoutParams(params);    invalidate();  }  /**   * header view 完成更新后恢复初始状态   *   */  public void onHeaderRefreshComplete() {    setHeaderTopMargin(-mHeaderViewHeight);    mHeaderImageView.setVisibility(View.VISIBLE);    mHeaderImageView.setImageResource(R.drawable.ic_pulltorefresh_arrow);    mHeaderTextView.setText(R.string.app_name);    mHeaderProgressBar.setVisibility(View.GONE);    // mHeaderUpdateTextView.setText("");    mHeaderState = PULL_TO_REFRESH;  }  /**   * Resets the list to a normal state after a refresh.   *   * @param lastUpdated   *      Last updated at.   */  public void onHeaderRefreshComplete(CharSequence lastUpdated) {    setLastUpdated(lastUpdated);    onHeaderRefreshComplete();  }  /**   * footer view 完成更新后恢复初始状态   */  public void onFooterRefreshComplete() {    setHeaderTopMargin(-mHeaderViewHeight);    mFooterImageView.setVisibility(View.VISIBLE);    mFooterImageView.setImageResource(R.drawable.ic_pulltorefresh_arrow_up);    mFooterTextView.setText(R.string.app_name);    mFooterProgressBar.setVisibility(View.GONE);    // mHeaderUpdateTextView.setText("");    mFooterState = PULL_TO_REFRESH;  }  /**   * Set a text to represent when the list was last updated.   *   * @param lastUpdated   *      Last updated at.   */  public void setLastUpdated(CharSequence lastUpdated) {    if (lastUpdated != null) {      mHeaderUpdateTextView.setVisibility(View.VISIBLE);      mHeaderUpdateTextView.setText(lastUpdated);    } else {      mHeaderUpdateTextView.setVisibility(View.GONE);    }  }  /**   * 获取当前header view 的topMargin   *   */  private int getHeaderTopMargin() {    LayoutParams params = (LayoutParams) mHeaderView.getLayoutParams();    return params.topMargin;  }  // /**  // * lock  // *  // */  // private void lock() {  // mLock = true;  // }  //  // /**  // * unlock  // *  // */  // private void unlock() {  // mLock = false;  // }  /**   * set headerRefreshListener   *   * @param headerRefreshListener   */  public void setOnHeaderRefreshListener(      OnHeaderRefreshListener headerRefreshListener) {    mOnHeaderRefreshListener = headerRefreshListener;  }  public void setOnFooterRefreshListener(      OnFooterRefreshListener footerRefreshListener) {    mOnFooterRefreshListener = footerRefreshListener;  }  /**   * Interface definition for a callback to be invoked when list/grid footer   * view should be refreshed.   */  public interface OnFooterRefreshListener {    public void onFooterRefresh(PullToRefreshView view);  }  /**   * Interface definition for a callback to be invoked when list/grid header   * view should be refreshed.   */  public interface OnHeaderRefreshListener {    public void onHeaderRefresh(PullToRefreshView view);  }}