Android ListView:由于空指针异常,启动时无法将项目居中

Android ListView:由于空指针异常,启动时无法将项目居中,android,android-listview,Android,Android Listview,这是我第一次在这里发表文章,我是一个愚蠢的新手,所以我希望有人能帮助我,原谅我的无知 我有一个用ArrayAdapter填充的ListView。当我滚动或单击时,我希望所选项目或离垂直中心最近的项目被强制到屏幕的确切垂直中心。如果我调用listView.setSelection(int位置),它会将所选位置与屏幕顶部对齐,因此我需要使用listView.setSelectionFromTop(位置,偏移)。为了找到偏移量,我从ListView高度的一半中选取视图高度的一半 因此,我可以很容易地在

这是我第一次在这里发表文章,我是一个愚蠢的新手,所以我希望有人能帮助我,原谅我的无知

我有一个用ArrayAdapter填充的ListView。当我滚动或单击时,我希望所选项目或离垂直中心最近的项目被强制到屏幕的确切垂直中心。如果我调用listView.setSelection(int位置),它会将所选位置与屏幕顶部对齐,因此我需要使用listView.setSelectionFromTop(位置,偏移)。为了找到偏移量,我从ListView高度的一半中选取视图高度的一半

因此,我可以很容易地在OnItemClick或OnScrollStateChanged中垂直居中放置我的项目,如下所示:

        int x = listView.getHeight();
        int y = listView.getChildAt(0).getHeight();                 
        listView.setSelectionFromTop(myPosition, x/2 - y/2);
这一切都很好。我的问题是初始的ListView设置。我希望在活动开始时将项目居中,但我不能,因为我从以下位置获得NullPointerException:

int y = listView.getChildAt(0).getHeight();
我理解这是因为当我从OnCreate()或OnResume()调用它时,ListView还没有呈现,所以它没有子对象

所以我的问题很简单:如何在启动时强制ListView进行渲染,以便获得所需的高度值?或者,是否有其他方法在ListView中垂直居中显示项目

提前感谢您的帮助

int y = listView.getChildAt(0).getHeight();
private boolean listViewReady = false;

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

    if (!listViewReady){
        Thread timer = new Thread() {
            public void run() {
                try{
                    sleep(1);
                }catch (InterruptedException e) {
                    e.printStackTrace();
                }finally{                   
                    runOnUiThread(new Runnable() {
                         public void run() {
                             myPosition = 2;
                             int x = listView.getHeight();
                             int y = listView.getChildAt(0).getHeight();                 
                             listView.setSelectionFromTop(myPosition, x/2 - y/2);
                             listViewReady = true;
                        }
                    });                     
                }
            }
        };
        timer.start();
    }//if !ListViewReady
我理解这是因为ListView尚未呈现,所以当我从
onCreate()
onResume()调用它时,它没有子对象

您应该在
onScroll
中调用它

listView.setOnScrollListener(new OnScrollListener() {

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {

    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
        int visibleItemCount, int totalItemCount) {
         //Write your logic here

         int y = listView.getChildAt(0).getHeight();




    }       
});

我在这里回答我自己的问题,但这是一个非常复杂的问题。我认为这很有趣,因为它揭示了ListView的行为

问题在于试图对尚不存在(尚未呈现)的数据(listview行)执行操作。getChildAt(int)为null,因为listview还没有子对象。我发现在创建活动时会立即调用onScroll(),所以我只是将所有内容都放在一个线程中,并延迟了getChildAt()调用。然后,我将整个过程封装在一个布尔包装器中,以确保只调用一次(在启动时)

有趣的是,我只需将通话延迟1毫秒,一切就都好了。这太快了,眼睛看不见

就像我说的,这都是黑客行为,所以我肯定这是个坏主意。谢谢你的帮助

int y = listView.getChildAt(0).getHeight();
private boolean listViewReady = false;

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

    if (!listViewReady){
        Thread timer = new Thread() {
            public void run() {
                try{
                    sleep(1);
                }catch (InterruptedException e) {
                    e.printStackTrace();
                }finally{                   
                    runOnUiThread(new Runnable() {
                         public void run() {
                             myPosition = 2;
                             int x = listView.getHeight();
                             int y = listView.getChildAt(0).getHeight();                 
                             listView.setSelectionFromTop(myPosition, x/2 - y/2);
                             listViewReady = true;
                        }
                    });                     
                }
            }
        };
        timer.start();
    }//if !ListViewReady

在我看来,我使用了一个简单的解决方案来达到同样的效果

mListView.post(new Runnable() {
   @Override
   public void run() {
      int height = mListView.getHeight();
      int itemHeight = mListView.getChildAt(0).getHeight();
      if (positionOfMyItem == myCollection.size() - 1) {
        // last element - > don't subtract item height
        itemHeight = 0;
    }
    mListView.setSelectionFromTop(position, height / 2 - itemHeight / 2);
   }
});
我想这对你有用。我确实看到onScroll()在活动开始时就被调用,事实上,它似乎被调用了好几次。每当滚动列表时,它也会被多次调用。但当我尝试与任何listview行通信时,仍然会得到Null,因此我假设它们仍然不存在。我正在使用OnScrollStateChanged,因为我可以在完成滚动后设置ListView位置(int scrollstate=OnScrollListener.SCROLL\u STATE\u IDLE)。