1

I have several expandable layouts in my Android App. When I click to expand a layout, the layout disapear outside the screen, and I have to manual scroll down to make it visible. How can I make the ScrollView automatically scroll down to make the clicked layout visible?

I tried using scrollView.scrollTo(0, textID.getBottom()); to scroll to the bottom of the layout element, but without luck.

Java:

expandableLayout1 = root.findViewById(R.id.expandable_layout1);
        button = (LinearLayout)root.findViewById(R.id.box_header);
        button.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view) {
                if (expandableLayout1.isExpanded()) {
                    expandableLayout1.collapse();
                } else {
                    expandableLayout1.expand();
                    scrollView.scrollTo(0, textID.getBottom());
                }
            }
        });

xml:

        <LinearLayout
            android:id="@+id/box"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <LinearLayout
                android:id="@+id/box_header"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="horizontal">

                <TextView
                    android:id="@+id/textID"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="title"
                    android:textColor="#ffffff"
                    android:textSize="16sp"/>

            </LinearLayout>

            <net.cachapa.expandablelayout.ExpandableLayout
                android:id="@+id/expandable_layout1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:el_duration="1000"
                app:el_expanded="false"
                app:el_parallax="0.5">

                
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="some text"
                    android:textColor="#ffffff"
                    android:textSize="12sp"/>
                
            </net.cachapa.expandablelayout.ExpandableLayout>

        </LinearLayout>
Frederik Petri
  • 451
  • 8
  • 24

1 Answers1

0

The problem you are facing is that the ExpandableLayout doesn't have time to finish opening before ScrollView already ends up scrolling to the bottom of it. So what ends up happening is that the ScrollView Scrolls to the bottom of the ExpandableLayout which hasn't fully opened yet. What you need to do is add a delay between the Layout opening and the ScrollView starting it's scroll function. Here is the code you need, I would try adjusting the milliseconds, you could probably drop them down below 1000 but not by much, still it's up to you to troubleshoot it a bit to make it just a tad bit faster and smoother. Also try using smoothScrollTo instead of scrollTo.

expandableLayout1 = root.findViewById(R.id.expandable_layout1);
    button = (LinearLayout)root.findViewById(R.id.box_header);
    button.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View view) {
            if (expandableLayout1.isExpanded()) {
                expandableLayout1.collapse();
            } else {
                expandableLayout1.expand();

                new Handler().postDelayed(new Runnable() {

                    @Override
                    public void run() {

                         scrollView.post(new Runnable() {
                             @Override
                             public void run() {

                                 scrollView.scrollTo(0, textID.getBottom());

                             }
                         });

                    }
                 }, 1000 ); // time in milliseconds
                
            }
        }
    });

And here is the code that I added in it's raw form, might help you understand it a bit easier.

new Handler().postDelayed(new Runnable() {
 @Override
 public void run() {

 // do something

 }
}, 1000 );  // time in milliseconds
Jinglepot
  • 40
  • 6