滚动其父ListView时使子视图无效的有效方法?

时间:2014-07-05 13:00:00

标签: android listview ondraw invalidation

我有一个ListView,其自定义子视图作为其行布局。我的要求是仅在滚动ListView时使行的子视图无效。现在我通过从子视图的onDraw()方法调用ChildView.invalidate()来实现这一点,并且事情按照我的预期很好地工作,但是即使ListView没有滚动,这种方法也会使子视图无效,所以我观察到它在应用程序运行时消耗大量CPU。我正在寻找一个廉价的解决方案。 滚动ListView时是否有回调?我看不到任何东西。 请回答,谢谢。

protected void onDraw (Canvas canvas) {
   drawBackground(canvas);
   drawContent(canvas); 

   this.invalidate();//Recursive calling...? But no error or warnings issued.
   //super.onDraw(canvas);               
}  

1 个答案:

答案 0 :(得分:0)

@pskink谢谢它有效!但是并没有解决这个问题"用廉价的方法做到这一点"。请参考代码中的注释并回答如何处理onScroll()的参数,以便仅使屏幕上可见的视图无效。 View.getChildAt(int).invalidate不起作用

import android.app.ListActivity;
import android.widget.ListView;
import android.widget.AbsListView;

public class MyListActivity extends ListActivity implements ListView.OnScrollListener {

...         

@Override    
public void onCreate(Bundle savedInstance) {        
    super.onCreate(savedInstance);      
    setContentView(R.layout.list_activity_layout);          

    getListView().setOnScrollListener(this);    

}

....

@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
    Log.e("MyListActivity", "onScrollStateChanged()");
}

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

    Log.e("MyListActivity", "onScroll()");
    Log.e("view.getId():", "" + view.getId());


    //view.invalidateViews();//Calling this method does the job, but it seems that It might re-measure                              
                            // and redraw each and every views of each and every rows in the ListView..!
                            // So, still it is an expensive approach. is it?, but better than doing
                            // recursive calling of invalidate(); am I right?
                            // I am not satisfied with this approach.

    // At least it should be possible to invalidate the views which are visible on the screen, as we expect from -
    // the arguments of this method.
    // Let me attempt to do it, shown below..               
    if(visibleItemCount != 0){
        int lastVisibleItemCount = firstVisibleItem + visibleItemCount;
        for(int i=firstVisibleItem; i<lastVisibleItemCount; i++){
            if(view.getChildAt(i) != null){
                view.getChildAt(i).invalidate();// Not works.
            }               
            Log.e("view.getItemIdAtPosition(i):", "" + view.getItemIdAtPosition(i));
        }
    }       
  } 
}

@pskink这是我正在寻找的确切解决方案。它只会使单个子视图无效,该视图位于可见范围内。它没有任何问题。

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

    //view.invalidateViews();//It does.., but still being expensive...!

    //The following only invalidates a single child view of the Row view in the visibility range.
    //Initializing i=0 may seem unnecessary, but it resolves many unexpected behavior of
    //the ListView when it is initialized to i=firstVisibleItem. 
    if(visibleItemCount != 0){
        int lastVisibleItemCount = firstVisibleItem + visibleItemCount;;                        
          for(int i=0; i<lastVisibleItemCount; i++){
            mRowView = mListView.getChildAt(i);//returns the row view.
            if(mRowView != null){
                mChildView = (CustomChildView) mRowView.findViewById(R.id.custom_child_view);//Single child of the Row View.                
                if(mChildView != null){
                    mChildView.invalidate();//only invalidates the required Child view of the row view.
                }                                       
            }
            Log.e("Row view pos: ", "" + i);
        }
    }       
}