2011-05-23 6 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には、次のonScrollメソッドを持つOnScrollListenerがあります。

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を呼び出します。

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 Iは同じisSpinVisibleフラグに他の方法をチェック以外のコード、およびスワップGONEと見えるhideSpinner()を呼び出し中 - そのonPreExecuteでIはshowSpinner()を呼び出します。スワップコードは、私が知る限り、一度呼び出されますが、上下にスクロールすると、進行状況バーが表示され、最後の複数のエントリが表示されます。

I)は、(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がnullであり、プログレスバーのいくつかは、まだ現れ。これをどうやって解決するのですか?あるいは、これを行う良い方法がありますか? (私は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の子どもには決して触れないでください。実際には、アダプタのgetView()ネストを残した後は、完全に独立しているとみなし、直接の制御から完全に離してください。あなたがそれらを制御できる唯一の方法は、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を使用することをお勧め。リストの最後の要素が表示されたら、自動的に多くの要素が読み込まれます。

関連する問題