Search code examples
androidandroid-scrollviewonscrollchanged

onScrollChange() is not being called for every pixel scrolled on ScrollView


I want to add new child views after every 50 pixels of scrolling but the statement Log.d("scroll",scrollY+":"+oldScrollY); is missing some values i.e. scrollY = 149 and scrollY = 151 are there in Log but scrollY = 150 is missing. So the code doesn't run for scrollY = 150 and new child views is not added.

Although it works as it should for most of the values of scrollY but for few values of scrollY, the event is not being triggered.

How can i resolve this issue? Or is there any other way to achieve this.

public class MainActivity extends AppCompatActivity implements ScrollViewListener {

    RelativeLayout parent;
    TextView height;
    ObservableScrollView scrollView;
    int position=1;
    View view1,view2;

    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        parent = (RelativeLayout) findViewById(R.id.parent);
        scrollView = (ObservableScrollView) findViewById(R.id.scroll_view);

        LayoutInflater inflater = LayoutInflater.from(this);
        view1 = inflater.inflate(R.layout.education,null, false);
        view1.setId(R.id.parent+position);

        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                                                                             ViewGroup.LayoutParams.WRAP_CONTENT);
        params.addRule(RelativeLayout.LEFT_OF,R.id.divider);
        params.topMargin = 100;
        params.rightMargin = 3;
        parent.addView(view1, params);
        position++;

        final Animation leftAnimation = new TranslateAnimation(view1.getX()-50,view1.getX(),view1.getY()+100,view1.getY());
        leftAnimation.setDuration(1000);
        view1.setAnimation(leftAnimation);

        scrollView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
            @Override
            public void onScrollChange(View view, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
                Log.d("scroll",scrollY+":"+oldScrollY);
                if((scrollY-oldScrollY)>0 && scrollY%50 == 0)
                {
                    Log.d("scroll","abcghfg");

                    if(position%2==0)
                    {
                        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                                ViewGroup.LayoutParams.WRAP_CONTENT);
                        params.addRule(RelativeLayout.RIGHT_OF,R.id.divider);
                       // params.topMargin = (position-1)*(view1.getLayoutParams().height)+position*100;
                        params.topMargin = 30;
                        params.leftMargin = 3;
                        params.addRule(RelativeLayout.BELOW,parent.getChildAt(position-1).getId());
                        Log.d("scroll","abc");
                        view2 = LayoutInflater.from(MainActivity.this).inflate(R.layout.education,null,false);
                        view2.setId(R.id.parent+position);

                        Animation rightAimation = new TranslateAnimation(view2.getX()+50,view2.getX(),view2.getY()+100,view2.getY());
                        rightAimation.setDuration(1000);
                        view2.startAnimation(rightAimation);

                        parent.addView(view2, params);
                    }
                    else
                    {
                        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                                ViewGroup.LayoutParams.WRAP_CONTENT);
                        params.addRule(RelativeLayout.LEFT_OF,R.id.divider);
                        //params.topMargin = (position-1)*(view1.getLayoutParams().height)+position*100;
                        params.topMargin = 30;
                        params.rightMargin = 3;
                        params.addRule(RelativeLayout.BELOW,parent.getChildAt(position-1).getId());
                        Log.d("scroll","def");
                        view2 = LayoutInflater.from(MainActivity.this).inflate(R.layout.education,null,false);
                        view2.setId(R.id.parent+position);

                        Animation animation = new TranslateAnimation(view2.getX()-50,view2.getX(),view2.getY()+100,view2.getY());
                        animation.setDuration(1000);
                        view2.startAnimation(animation);

                        parent.addView(view2, params);
                    }
                    position++;
                }
            }
        });
    }
}

Thanks in advance.


Solution

  • Android doesn't render every pixel in a scroll, because it would be bad for performance. If you scroll really slow, you will see that your callback will be called for every pixel, but if you scroll fast, it will be called just when the render triggers.

    In your case, you need to check if it rendered 50 or more pixels since last time you rendered the last view.