7

I've got two ListView objects that I would like to scroll together. They are side-by-side, so if one scrolls a certain amount, the other scrolls that same amount. I've found some examples on how to do this, but I believe that they rely on the items in the ListView being the same height (correct me if I am wrong). The items in one of my ListView objects are taller than the ones in the other, spanning 2-3 items.

How do I "lock" these 2 ListView objects together?

EDIT: Here's a screenshot of what I have, maybe it will better explain what I'm going for. The left side (red) is a list of items and the right side is a separate list. You can see how the lists don't align perfectly, so it isn't exactly a grid. What I would like to do is have this act like one big list, where scrolling either list will also scroll the other.

App Screenshot

compuguru
  • 1,035
  • 1
  • 10
  • 20
  • 1
    Rather than trying to link two listviews, why don't you merge the content of the two into one ListView? – The Nail Dec 03 '11 at 23:08

4 Answers4

7

I created a rough class that does basically what I wanted to do. It's not smart enough to handle if the 2nd list is longer than the 1st or if the orientation changes, but it's good enough to get the concept down.

To set it up:

list1.setOnScrollListener(new SyncedScrollListener(list2));
list2.setOnScrollListener(new SyncedScrollListener(list1));

SyncedScrollListener.java

package com.xorbix.util;

import android.view.View;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;

public class SyncedScrollListener implements OnScrollListener{
    int offset;
    int oldVisibleItem = -1;
    int currentHeight;
    int prevHeight;
    private View mSyncedView;


    public SyncedScrollListener(View syncedView){

        if(syncedView == null){
            throw new IllegalArgumentException("syncedView is null");
        }

        mSyncedView = syncedView;
    }

    public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) {

        int[] location = new int[2];

        if(visibleItemCount == 0){
            return;
        }

        if(oldVisibleItem != firstVisibleItem){

            if(oldVisibleItem < firstVisibleItem){
                prevHeight = currentHeight;
                currentHeight = view.getChildAt(0).getHeight();

                offset += prevHeight;

            }else{
                currentHeight = view.getChildAt(0).getHeight();

                View prevView;
                if((prevView = view.getChildAt(firstVisibleItem - 1)) != null){
                    prevHeight = prevView.getHeight();
                }else{
                    prevHeight = 0;
                }

                offset -= currentHeight;
            }

            oldVisibleItem = firstVisibleItem;
        }

        view.getLocationOnScreen(location);
        int listContainerPosition = location[1];

        view.getChildAt(0).getLocationOnScreen(location);
        int currentLocation = location[1];

        int blah = listContainerPosition - currentLocation + offset;

        mSyncedView.scrollTo(0, blah);

    }

    public void onScrollStateChanged(AbsListView view, int scrollState) {
        // TODO Auto-generated method stub

    }
}
compuguru
  • 1,035
  • 1
  • 10
  • 20
  • 1
    Sorry this is not working on second list scrol it disble bottom view many issue – CoronaPintu Jun 30 '14 at 05:55
  • Yep, this is also not working for me. I mean, the scroll link works, but new items are not drawn on the passive scrolled list, and overall it gets chaotic. – Graph Sep 19 '15 at 18:51
0

I ended up using the top s/o answer here: Android. Scrolling 2 listviews together

Intercepting and redirecting events seems to be a lot more elegant and consistent than trying to do my own math on the dimensions and state of the listviews.

Community
  • 1
  • 1
jmaculate
  • 2,976
  • 2
  • 17
  • 14
0

I think it is more appropriate to use a GridView with 2 columns, something like this:

<GridView
    android:id="@+id/grid_view"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:numColumns="2"
    />
gwvatieri
  • 5,133
  • 1
  • 29
  • 29
0

What I would like to do is to listen to the scrolling event for the left listview and then scroll the right listview by an proper offset. Below is my code, I tested it(very simple, just show you my thought) and you may add your code based on it.

package viewTest.example.hy;

import android.app.Activity;

import android.os.Bundle;

import android.widget.AbsListView;

import android.widget.ArrayAdapter;

import android.widget.ListView;

import android.widget.AbsListView.OnScrollListener;

public class ViewTestActivity extends Activity {


private ArrayAdapter<String> adapter0;
    private ArrayAdapter<String> adapter1;
    private String[] array0;
    private String[] array1;
    private ListView lv0;
    private ListView lv1;


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    array0 = getResources().getStringArray(R.array.LV0);//letters from A to O
    array1 = getResources().getStringArray(R.array.LV1);//numbers from 1 to 14

    adapter0 = new ArrayAdapter<String>(this, R.layout.item, array0);
    adapter1 = new ArrayAdapter<String>(this, R.layout.item, array1);

    lv0 = (ListView) findViewById(R.id.listView1);
    lv1 = (ListView) findViewById(R.id.listView2);

    lv0.setAdapter(adapter0);
    lv1.setAdapter(adapter1);

    lv0.setOnScrollListener(new OnScrollListener() {

        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
            lv1.setSelection(firstVisibleItem);//force the right listview to scrollyou may have to do some calculation to sync the scrolling status of the two listview.
        }
    });

}

}

And this is the main.xml layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/layout"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal" >

<ListView
    android:id="@+id/listView1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_weight="1" 
    android:scrollbars="none">
</ListView>

<ListView
    android:id="@+id/listView2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:scrollbars="none" >
</ListView>

</LinearLayout>

Here is my screenshot: enter image description here

Huang
  • 4,812
  • 3
  • 21
  • 20