2013-03-13 69 views
0

我正在用ListView和PullToRefresh編寫自己的Android應用程序來刷新此列表。添加拉到刷新後,我得到了該錯誤:當我拉列表刷新一些項目被點擊。我該如何解決它? 這裏是我的MainActivity代碼:無法正確控制PullToRefresh

package ua.iqw.mistinfo.news; 

import android.os.Bundle; 

import android.view.Menu; 
import android.view.MotionEvent; 
import android.view.View.OnTouchListener; 

import java.util.ArrayList; 
import java.util.concurrent.ExecutionException; 

import ua.iqw.mistinfo.news.trace.ExceptionHandler; 
import ua.iqw.mistinfo.news.PullToRefreshListView; 
import ua.iqw.mistinfo.news.PullToRefreshListView.OnRefreshListener; 

import android.app.ListActivity; 
import android.app.ProgressDialog; 

import android.content.Intent; 
import android.util.Log; 

import android.view.View; 

    import android.widget.ListView; 
    import android.widget.Toast; 

public class MainActivity extends ListActivity implements OnTouchListener{ 

ArrayList<ListData> news; 
AsyncLoad asyncNews; 
RefreshList refresh; 
ProgressDialog spinner; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    // ExceptionHandler.register(this, 
    // "http://errors.bazalt-cms.com/add-android/"); 

    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    final PullToRefreshListView listView = (PullToRefreshListView)findViewById(android.R.id.list); 
    spinner = new ProgressDialog(MainActivity.this); 
    spinner.setMessage(getString(R.string.loading)); 
    spinner.show(); 

    Network net = new Network(this); 
    if (net.isNetworkAvailable() == true) { 
     Log.d("NETWORK", "Network is available!"); 
    } else { 

     Toast.makeText(this, getString(R.string.connect_error), 
       Toast.LENGTH_LONG).show(); 
    } 

    asyncNews = new AsyncLoad(MainActivity.this); 
    asyncNews.execute(); 

    listView.setOnRefreshListener(new OnRefreshListener() { 
     @Override 
     public void onRefresh() { 

      refresh = new RefreshList(MainActivity.this, listView); 
      refresh.execute(); 
     } 

    }); 

} 

public void onResume() { 
    super.onResume(); 

    if (spinner.isShowing()) { 
     spinner.dismiss(); 
    } 

} 

public void onListItemClick(ListView parent, View v, int position, long id) {//listener for click on listView item 


    try { 
     news = asyncNews.get(); 
    } catch (InterruptedException e) { 

     e.printStackTrace(); 
    } catch (ExecutionException e) { 

     e.printStackTrace(); 
    } 
    ListData ld = news.get(position); 

    spinner.setMessage(getString(R.string.loading)); 
    spinner.show(); 

    Intent intent = new Intent(MainActivity.this, DetailsActivity.class); 
    intent.putExtra("id", ld.id); 

    startActivity(intent); 

} 
} 

是否有可能設置onListItemClick一些超時? 或者它可以通過其他方式解決? 請幫幫我! P.S.對不起,我的英語)

回答

3
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; 


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.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); 
    } 

    @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 (mRefreshView.getBottom() > 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(); 
    } 
} 

試試吧

+0

非常感謝!它工作正常! – IQW 2013-03-13 15:27:28