I am trying to synchronize the positions of two ScrollViews. I'm trying to do this to display a tv guide listing.
I have created a custom class that extends RelativeLayout to display the guide. This relative layout has four children: an imageview in the top left corner, a HorizontalScrollView to display the column headers in the top right, a ScrollView to display the row headers at the bottom left, and a ScrollView in the bottom right that contains the listings. This ScrollView then contains a HorizontalScrollView, which in turn contains a LinearLayout with multiple child views that display the data. I hope this explains it clearly, but here's a diagram to make it clearer:
____________
|__|___hsv___|
| | |
| | sv -> |
| | hsv -> |
|sv| ll -> |
| | etc |
| | |
|__|_________|
I set it up like this because I wanted the guide listings to scroll both horizontally and vertically, but there's no scroll view that does this. Also, I want the row and column headers to display no matter what position the guide listings are at, but I want them to be lined up properly. So I'm trying to find a way to synchronize the positions of the two hsv's, and to also synchronize the positions of the two sv's. I'm also trying to do it in a way that avoids just running a handler every few milliseconds to poll one view and call scrollTo on the other.
I'm in no way sure that this is the best way to do it, but this is what I've come up with. If 开发者_运维知识库anybody has any other suggestions, please feel free!
Wouldn't it be worth implementing onTouchEvent(MotionEvent me) in all your panels? When one of your panels is scrolled, this method would be called, and it can make sure that all the others are kept synchronized.
Handling the touch events does not work 100%. The amount of scrolls in different views may not be in sync always.
Handling the touch events is not enough, because if you do a fast flinge the scrolling goes on for a while after releasing the touch. The solution is to override the computeScroll() method. Have a look at https://github.com/chrisjenx/ParallaxScrollView how it is done there.
You may have a look at this post: Link
What this guy is actually doing he creates custom ScrollViews and overrides the method onScrollChanged
, adds a listener and then synchronizes them before they are drawn to the screen.
What you can do now is adding as main frame a ScrollView
in a HorizontalScrollView
. The left bar would be a HorizontalScrollView
, and the top a ScrollView
. Then you register the main ScrollView
and the main HorizontalScrollView
to two seperate ScrollManagers
(see link above).
Then disable the scrolling of hsv and sv and add them to the appropriate ScrollManagers
. Then everything should work fine.
-
PS.
If you would use just the listeners themselves and not the ScrollManager
, you would have a sync delay of 1 frame.
I have achieved same layout by doing below things.
You will find SyncedScrollView in xml is custom scrollview used to synchronize two scrollviews.
You need to refer below two stackoverflow answers.
- SynchedScrollView andig answer
- optimized SynchedScrollView my answer
check below xml
<RelativeLayout
android:id="@+id/activity_main_linear_before_all_scroll"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/activity_main_empty_box"
android:layout_width="50dp"
android:layout_height="30dp"
android:text="xx"
android:gravity="center" />
<com.example.SyncedScrollView
android:id="@+id/activity_main_observable_scrollview_1"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_below="@+id/activity_main_empty_box"
android:fadeScrollbars="false"
android:overScrollMode="never"
android:scrollbars="none">
<LinearLayout
android:id="@+id/activity_main_linear_left_headers"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="50dp"
android:layout_height="30dp"
android:gravity="center"
android:padding="5dp"
android:text="row 1" />
<TextView
android:layout_width="50dp"
android:layout_height="30dp"
android:gravity="center"
android:padding="5dp"
android:text="row 2" />
<TextView
android:layout_width="50dp"
android:layout_height="30dp"
android:gravity="center"
android:padding="5dp"
android:text="row 3" />
</LinearLayout>
</com.example.SyncedScrollView>
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toEndOf="@+id/activity_main_empty_box"
android:layout_toRightOf="@+id/activity_main_empty_box"
android:fadeScrollbars="false"
android:overScrollMode="never">
<RelativeLayout
android:id="@+id/activity_main_body_relative"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/activity_main_top_headers"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="50dp"
android:layout_height="30dp"
android:gravity="center"
android:padding="5dp"
android:text="column 1" />
<TextView
android:layout_width="50dp"
android:layout_height="30dp"
android:gravity="center"
android:padding="5dp"
android:text="column 2" />
<TextView
android:layout_width="50dp"
android:layout_height="30dp"
android:gravity="center"
android:padding="5dp"
android:text="column 3" />
</LinearLayout>
<com.example.SyncedScrollView
android:id="@+id/activity_main_observable_scrollview_2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/activity_main_top_headers"
android:fadeScrollbars="false"
android:overScrollMode="never"
android:scrollbars="vertical">
<LinearLayout
android:id="@+id/activity_main_body"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/activity_main_body_row_1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:layout_width="50dp"
android:layout_height="30dp"
android:gravity="center"
android:padding="5dp"
android:text="1,1" />
<TextView
android:layout_width="50dp"
android:layout_height="30dp"
android:gravity="center"
android:padding="5dp"
android:text="1,2" />
<TextView
android:layout_width="50dp"
android:layout_height="30dp"
android:gravity="center"
android:padding="5dp"
android:text="1,3" />
</LinearLayout>
<LinearLayout
android:id="@+id/activity_main_body_row_2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:layout_width="50dp"
android:layout_height="30dp"
android:gravity="center"
android:padding="5dp"
android:text="2,1" />
<TextView
android:layout_width="50dp"
android:layout_height="30dp"
android:gravity="center"
android:padding="5dp"
android:text="2,2" />
<TextView
android:layout_width="50dp"
android:layout_height="30dp"
android:gravity="center"
android:padding="5dp"
android:text="2,3" />
</LinearLayout>
<LinearLayout
android:id="@+id/activity_main_body_row_3"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:layout_width="50dp"
android:layout_height="30dp"
android:gravity="center"
android:padding="5dp"
android:text="3,1" />
<TextView
android:layout_width="50dp"
android:layout_height="30dp"
android:gravity="center"
android:padding="5dp"
android:text="3,2" />
<TextView
android:layout_width="50dp"
android:layout_height="30dp"
android:gravity="center"
android:padding="5dp"
android:text="3,3" />
</LinearLayout>
</LinearLayout>
</com.example.SyncedScrollView>
</RelativeLayout>
</HorizontalScrollView>
</RelativeLayout>
Each cell is TextView here. so you can set background drawable to draw boxes (It will look like table)
Also you can add left headers, top headers and body TextView dynamically to create table dynamically.
This is screen shot of layout
Sorry for my pure English.
精彩评论