How do I synchronize scrollview positions of dynamic horizontal scroll views inside a container?
Asked Answered
R

1

0

I have a parent container in one of my activities which make a call to it's child containers consisting of a horizontal scrollview as one of the objects. Sort of like a recyclerview with row objects placed inside where there is a common row/item layout consisting of a horizontal scroll view.

My objective is to sync the positions of the horizontalscrollview such that, when i am scrolling horizontally on one of the objects from position 1 to position 2, all the other items containing horizontal scrollview get updated from position 1 to position 2.

Here's my main container code: (Activity code)

 for (int index = 0; index < roomCount; index++) {
        Room r2 = ((LobbyReservationRowView) container.getChildAt(index))
                .getRoom();
        // Log.d("Lobby", "sorting: " + r.getName() + ":" + r.isFree() +
        // " -- " + r2.getName() + ":" + r2.isFree());

        if (r.equals(r2)) {
            Log.d("LobbyActivity", "duplicate room -- " + r.getEmail());
            // XXX: minor logic error; same room
            // someone else requested also an update, and we got rooms twice
            container.removeViewAt(index);
            container.addView(v, index);
            added = true;
            break;
        } else if (roomCmp.compare(r, r2) < 0) {
            container.addView(v, index);
            added = true;

            break;
        }

    }
    if (!added) {
        container.addView(v);

    }

where container is the layout containing the following layout as it's child:( the above code iterates over this layout to generate subsequent rows)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:orientation="vertical"
    android:gravity="center_vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <RelativeLayout
            android:layout_width="match_parent"
            android:background="#232527"
            android:layout_marginStart="16dp"
            android:layout_marginEnd="16dp"
            android:layout_height="109dp">
        <ImageView
            android:id="@+id/roomDefaultIcon"
            android:layout_width="116dp"
            android:layout_height="82dp"
            android:src="@drawable/75"
            android:contentDescription="@string/default_room_icon_content_description" />
            <LinearLayout
                android:id="@+id/titleLayout"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical|center"
                android:layout_toEndOf="@id/roomDefaultIcon"
                android:layout_marginStart="16dp"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/roomNameLabel"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textColor="@color/white"
                    android:layout_marginTop="20dp"
                    android:textStyle="bold"
                    android:textSize="14sp"
                    android:text="@string/tech_room" />

                <TextView
                    android:id="@+id/roomInfoLabel"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textColor="@color/TextInfoColor"
                    android:visibility="gone"
                    android:text="(42 persons)" />
            </LinearLayout>
            <HorizontalScrollView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@+id/roomDefaultIcon"
                android:id="@+id/horizontal_timebar_view"
                android:fillViewport="true">
                <com.roombooking.androidview.TimeBarView
                    android:id="@+id/mainTimeBarView"
                    android:layout_width="wrap_content"
                    android:layout_height="50dp"
                    android:orientation="horizontal"
                    >
                    <Button android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Button One"
                        android:visibility="invisible"/>
                    <Button android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Button Two"
                        android:visibility="invisible"/>
                    <Button android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Button Three"
                        android:visibility="invisible"/>
                    <Button android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Button Four"
                        android:visibility="invisible"/>


                </com.roombooking.androidview.TimeBarView>
            </HorizontalScrollView>
        </RelativeLayout>

    </LinearLayout>



    <ViewSwitcher
        android:id="@+id/modeSwitcher"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:inAnimation="@animator/fadein"
        android:outAnimation="@animator/fadeout">

        <LinearLayout
            android:id="@+id/normalMode"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_marginBottom="10dp"
            android:layout_marginEnd="0dp"
            android:layout_marginRight="0dp"
            android:layout_marginTop="10dp"
            android:orientation="horizontal"
            android:visibility="visible"
            android:weightSum="9" >

            <Button
                android:id="@+id/bookNowButton"
                android:layout_width="100dp"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_weight="3"
                android:layout_marginStart="10dp"
                android:background="@drawable/button_background"
                android:focusable="true"
                android:text="@string/book_now"
                android:textColor="@android:color/white"
                android:layout_marginLeft="10dp" />

            <TextView
                android:id="@+id/roomStatusLabel"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical"
                android:layout_marginLeft="20dp"
                android:layout_marginStart="20dp"
                android:layout_weight="5"
                android:minWidth="100dp"
                tools:text="&lt;status&gt;" />

            <Button
                android:id="@+id/calendarButton"
                android:layout_width="24dp"
                android:layout_height="24dp"
                android:layout_gravity="center_vertical|start"
                android:background="@drawable/calendar_small_grey"
                android:focusable="true" />


        </LinearLayout>


        <LinearLayout
            android:id="@+id/bookingMode"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:gravity="center_vertical"
            android:orientation="vertical"
            android:paddingBottom="8dp">

            <ImageButton
                android:id="@+id/cancelButton"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="top|end"
                android:layout_marginEnd="10dp"
                android:layout_marginRight="10dp"
                android:layout_marginTop="10dp"
                android:background="@drawable/close_button_states"
                android:contentDescription="@string/cancel_reservation" />

            <com.roombooking.android.view.CustomTimeSpanPicker2
                android:id="@+id/timeSpanPicker2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_marginBottom="16dp" />

            <AutoCompleteTextView
                android:id="@+id/autoCompleteTextView1"
                android:layout_width="230dp"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_marginBottom="10dp"
                android:layout_marginLeft="10dp"
                android:layout_marginRight="10dp"
                android:layout_marginTop="10dp"
                android:completionHint="Your name"
                android:completionThreshold="2"
                android:hint="@string/hint_your_name"
                android:imeOptions="actionDone"
                android:inputType="textCapWords|textFilter"
                android:lines="1"
                android:maxLines="1"
                android:textColor="@color/button_color"
                android:textColorHint="@color/CalendarWeekTextColor"/>

            <TextView
                android:layout_gravity="center"
                android:id="@+id/hintText"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:visibility="gone"
                android:text="@string/hintText"
                android:textColor="@color/CalendarWeekTextColor"/>

            <Button
                android:id="@+id/reserveButton"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_marginBottom="10dp"
                android:layout_marginTop="10dp"
                android:background="@drawable/button_background"
                android:focusable="true"
                android:text="@string/button_reserve"
                android:textColor="@android:color/white" />
            <TextView
                android:id="@+id/newRoomStatusLabel"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical|start"
                android:layout_marginLeft="20dp"
                android:layout_marginStart="20dp"
                android:layout_weight="5"
                android:textColor="@android:color/black"
                android:minWidth="100dp"
                 />

            <Button
                android:id="@+id/newCalendarButton"
                android:layout_width="24dp"
                android:layout_height="24dp"
                android:layout_gravity="center_vertical|end"
                android:background="@drawable/calendar_small_grey"
                android:focusable="true" />
        </LinearLayout>
    </ViewSwitcher>
</LinearLayout>

My point of focus is the HorizontalScrollView containing the timebar, which has positions 1 to 10. If I scroll to position 5 for example, the next subsequent rows should have the scrollbar position at 5 aswell, but I am not able to sync them. Any idea what could be missing from my code? Just for reference , here's LobbyReservationRowView class code snippet:

public class LobbyReservationRowView extends FrameLayout implements
        OnClickListener, OnItemClickListener, HorizontalScrollView.OnScrollChangeListener {

    @BindView(R.id.horizontal_timebar_view)
    HorizontalScrollView mHorizontalTimeBarView;

 @Override
    public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {

        mHorizontalTimeBarView.scrollTo(mHorizontalTimeBarView.getScrollX(),0);
    }

}

Happy to share the entire sample project if need be

Revengeful answered 14/11, 2019 at 2:13 Comment(3)
Have you tried it with the two recycler views? Because it's easy to manage.Vasquez
even with recyclerviews it ended up being the same issue. is there a way to sync them with the code I have, by somehow customizing the container or scrollview to achieve horizontal scrollview syncing?Revengeful
For syncing ScrollViews in their simplest form, check hereHorsey
S
0

You can achieve the synchronized scrolling with LiveData from Android Architecture Components. Declare an interface

interface LobbyReservationHSVListener{
        void updateScrollPosition(int scrollX);
    }

Declare a MutableLiveData variable and implement the LobbyReservationHSVListener in your activity like below:

public class HorizontalActivity extends AppCompatActivity implements
        LobbyReservationHSVListener {

    MutableLiveData<Integer> hsvPosition = new MutableLiveData<Integer>();

    @Override
    public void updateScrollPosition(int scrollX) {
        hsvPosition.setValue(scrollX);
    }
}

In onCreate in your activity start observing the MutableLiveData you declared. Whenever its value changes, loop through all children views of container and update their scroll positions.

hsvPosition.observe(this,new Observer<Integer>() {
            @Override
            public void onChanged(Integer integer) {
                for(int i=0; i<container.getChildCount();i++){
                    HorizontalScrollView hsv = container.getChildAt(i).findViewById(R.id.horizontal_timebar_view);
                    hsv.smoothScrollTo(integer,0);
                }
            }
        });

In your LobbyReservationRowView create a function to set the LobbyReservationHSVListener object and call updateScrollPosition whenever scroll changes.

public class LobbyReservationRowView extends FrameLayout implements
        OnClickListener, OnItemClickListener, HorizontalScrollView.OnScrollChangeListener {

    private LobbyReservationHSVListener hsvUpdateListener;

    @BindView(R.id.horizontal_timebar_view)
    HorizontalScrollView mHorizontalTimeBarView;

    public void setHSVUpdateListener(LobbyReservationHSVListener hsvUpdateListener){
        this.hsvUpdateListener = hsvUpdateListener;
    }

 @Override
    public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {

        hsvUpdateListener.updateScrollPosition(scrollX);
    }

}

Don't forget to call setHSVUpdateListener(this) on your LobbyReservationRowView object whenever adding it to your container

You should get something like this:

enter image description here

Sweitzer answered 19/11, 2019 at 14:44 Comment(4)
can you post the github link to the above project aswell? would be really helpful! thanks for your answer btw, will test it outRevengeful
You welcome you can find the sample repo here github.com/EphraimNetWorks/SynchronizedScrollingSweitzer
stackoverflow doesnt allow me to award bounty until the next 18 hours, will assign it to you in 18 hours!Revengeful
Networks any idea about this one : #59080151Revengeful

© 2022 - 2024 — McMap. All rights reserved.