2011-05-23 39 views
0

我想创建一个列表,显示一个不确定的进度条作为最后一个条目,而它正在获取更多的数据。我可以显示栏并获取/添加数据,但在加载时上下滚动会导致出现多个进度条。在列表视图中不确定的进度条

我有一个使用ArrayAdapter的ListActivity。每行都有一个布局如下。

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="fill_parent" android:layout_height="wrap_content" 
android:background="@drawable/textlines" android:padding="2dip"> 
<LinearLayout android:layout_width="fill_parent" 
    android:layout_height="wrap_content" android:id="@+id/rowContent"> 
    <TextView android:height="20sp" android:text="" 
     android:id="@+id/search_display" android:layout_width="fill_parent" 
     android:textSize="16sp" android:layout_height="20sp" android:gravity="left" /> 
</LinearLayout> 
<LinearLayout android:layout_height="wrap_content" 
    android:layout_width="fill_parent" android:id="@+id/rowSpinner" 
    android:padding="3px" android:gravity="center" android:visibility="gone"> 
    <ProgressBar android:layout_width="wrap_content" 
     android:layout_height="wrap_content" android:id="@+id/progress" 
     android:indeterminate="true" /> 
</LinearLayout> 
</RelativeLayout> 

ListView的OnScrollListener具有以下onScroll方法。

public void onScroll(final AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) 
{ 
    // detect if last item is visible 
    if ((visibleItemCount < totalItemCount) 
     && (firstVisibleItem + visibleItemCount == totalItemCount)) 
    { 
    if (false == scrollTaskRunning) 
    { 
     scrollTaskRunning = true; 
     getMoreData(totalItemCount); 
    } 
    } 
} 

getMoreData调用该得到更多的数据添加到适配器的的AsyncTask。在其onPreExecute我请showSpinner() -

private void showSpinner() 
{ 
    // nothing to do if there's already a spinner visible 
    if (isSpinVisible == true) return; 

    // hide the progress spinner 
    if (0 < lvList.getChildCount()) 
    { 
    View vRow = lvList.getChildAt(lvList.getChildCount() - 1); 
    vRow.findViewById(R.id.rowContent).setVisibility(View.GONE); 
    vRow.findViewById(R.id.rowSpinner).setVisibility(View.VISIBLE); 
    } 
    isSpinVisible = true; 
} 

,并在其onPostExecute/onCancelled我请hideSpinner(),其是相同的代码,除了检查isSpinVisible标志的其他方式,以及消失,VISIBLE交换。就我所知,交换代码只会被调用一次,但如果您上下滚动,最后会显示多个条目,进度条可见。

我试着这样做不是为hideSpinner() -

private void hideSpinner() 
{ 
    // nothing to do if there's no spinner visible 
    if (isSpinVisible == false) return; 

    // show the progress spinner 
    int iChildCount = lvList.getChildCount(); 
    if (0 < lvList.getChildCount()) 
    { 
    for (int i = 0; i < iChildCount; i++) 
    { 
     View vRow = lvList.getChildAt(iChildCount); 
     if (null != vRow) 
     { 
     vRow.findViewById(R.id.rowContent).setVisibility(View.VISIBLE); 
     vRow.findViewById(R.id.rowSpinner).setVisibility(View.GONE); 
     } 
    } 
    } 
    else if (null != pbSearch) 
    { 
    pbSearch.setVisibility(View.GONE); 
    } 
    isSpinVisible = false; 
} 

但VROW是空的,一些进度条仍然显示出来。我该如何解决?或者,有没有更好的方法来做到这一点? (我想我也许可以做我的ArrayAdapter的getView()法的东西,但我不能工作了)


ETA:此answer似乎可以解释我遇到的问题,但知道这并没有帮助我找到解决办法。


ETA2:我试着这样做:

final LayoutInflater mInflater = (LayoutInflater) 
        getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
aapSearchResults = new ArrayAdapter<ParsedXML>(this, R.layout.search_row, saData) 
{ 
    @Override 
    public View getView(int position, View convertView, ViewGroup parent) 
    { 
    View row; 

    // get the view 
    if (null == convertView) 
    { 
     row = mInflater.inflate(R.layout.search_row, null); 
    } 
    else 
    { 
     row = convertView; 
    } 

    // bind the data to the view 
    TextView tv = (TextView) row.findViewById(R.id.search_display); 
    tv.setText(getItem(position).name); 

    // show data, hide spinner 
    row.findViewById(R.id.rowContent).setVisibility(View.VISIBLE); 
    row.findViewById(R.id.rowSpinner).setVisibility(View.GONE); 

    // if the current position is the last, and a task is running, 
    // show the progress bar   
    if (taskRunning && (position == this.getCount()-1)) 
    { 
     row.findViewById(R.id.rowContent).setVisibility(View.GONE); 
     row.findViewById(R.id.rowSpinner).setVisibility(View.VISIBLE);    
    } 


    return row; 
    } 
}; 
lvList.setAdapter(aapSearchResults); 

,但我清楚地做一个逻辑错误仍然,因为有时候滚动向上和向下,现在我得到空白项。 (是否因为计数改变了?)

回答

2

一般而言,您不应该直接碰触ListView的孩子。事实上,在他们离开适配器的嵌套后,您应该认为它们完全独立,完全脱离了您的直接控制。你可以控制它们的唯一方法是调用notifyDataSetChanged()并让ListView创建新的。

要解决你的问题,这样做:

public class MyAdapter extends ArrayAdapter[…]{ 
    //[…] 

    private boolean mIsLoading = false; 

    public void setIsLoading(boolean isLoading){ 
     if (mIsLoading != isLoading){ 
      mIsLoading = isLoading; 
      notifyDataSetChanged(); 
     } 
    } 

    @Override 
    public int getCount(){ 
     return super.getCount() + (isLoading ? 1 : 0); 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     if (mIsLoading && position == (getCount() - 1)){ 
      //return your progress view goes here. Ensure that it has the ID R.id.progress; 

     }else{ 
      if (convertView != null && convertView.getId() == R.id.progress){ 
       convertView = null; 
      } 
      return super.getView(position, convertView, parent); 
     } 
    } 
} 
0

我会建议你使用一个BaseAdapter来代替。当列表中最后一个显示时,它会自动加载更多元素。