Search code examples
androidlistviewscrollsmooth-scrollingonscrolllistener

onScrollStateChanged wont scroll smooth when Scroll_State_Idle


I got a listView, containing several items with the same hight in fullscreen. When i release scrolling, I want to scroll smooth automatically to that item, which takes the most space on the screen. The smoothscrolling itself works when i scroll to a random position and hit a button (for example when 60% of the firstVisible item is visible and 40% of the following item is visible it automatically scrolls smooth to the firstVisible item to be fullscreen after button-OnClick) see Code:

    ListView mylistView= (ListView)findViewById(R.id.ListViewLayout);
    int midScreen = mylistView.getMeasuredHeight() / 2;

    public void onClick(View v) {

    View v = mylistView.getChildAt(0);
    int top = (v == null) ? 0 : v.getTop();
    top =-top;
    if (top <= midScreen) {
        mylistView.smoothScrollBy(-top, 1000); // if first item takes more space, scroll up
        } else { 
            mylistView.smoothScrollBy((midScreen*2)-top, 1000); // if second item takes more space, scroll down
           }

now i want this working procedure to be called, when the list stops scrolling. I created an onScrollListener and in onScrollStateChanged i tried this if the listScroll stops (so state 0, idle):

        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
            if (scrollState==OnScrollListener.SCROLL_STATE_IDLE) {                  
                View vX = mylistView.getChildAt(0);
                int top = (vX == null) ? 0 : vX.getTop();
                top =-top;
                if (top <= midScreen) {
                    mylistView.smoothScrollBy(-top, 1000);
                } else mylistView.smoothScrollBy((midScreen*2)-top, 1000);
            }
         }

The problem: instead of scrolling smooth 1second to that exact position to show the wanted item in fullscreen, it jumps as fast as it can. The smoothScrollBy is no more smooth when it is called in state 0. Why is that and is there any solution?


Solution

  • Ok i managed to run the smoothScroll in a runnable with a handler and now it works! If someone has the same problem, here comes the code

        listViewAnlagen.setOnScrollListener(new OnScrollListener() {
    
            @Override
            public void onScroll(AbsListView view, int firstVisibleItem,
                    int visibleItemCount, int totalItemCount) { 
                }
    
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
    
                if (scrollState==OnScrollListener.SCROLL_STATE_IDLE) {
    
                    View vX = listViewAnlagen.getChildAt(0);
                    int top = (vX == null) ? 0 : vX.getTop();
                    top =-top;
                    if (top <= mitteScreen) {                       
                        handler.post(obenRunnable);
                    } else { 
                        handler.post(untenRunnable);
                        }
    
                }
            }
    
            Handler handler = new Handler();
            Runnable obenRunnable = new Runnable()
            {
                public void run() 
                {
    
                    View vX = listViewAnlagen.getChildAt(0);
                    int top = (vX == null) ? 0 : vX.getTop();
                    top =-top;
                    listViewAnlagen.smoothScrollBy(-top, 200);
                }
            };
            Runnable untenRunnable = new Runnable()
            {
                public void run() 
                {
                    View vX = listViewAnlagen.getChildAt(0);
                    int top = (vX == null) ? 0 : vX.getTop();
                    top =-top;
                    listViewAnlagen.smoothScrollBy((mitteScreen*2)-top, 200);
                }
            };  
        });