一起滚动列表视图

7
我有两个ListView对象,我希望让它们一起滚动。它们是并排的,所以如果一个滚动了一定的距离,另一个也会滚动同样的距离。我找到了一些如何做到这一点的示例,但我认为它们依赖于ListView中的项目具有相同的高度(如果我错了,请纠正我)。其中一个ListView对象中的项目比另一个高,跨越2-3个项目。
如何将这两个ListView对象“锁定”在一起?
编辑:这里是我拥有的截图,也许它会更好地解释我的意思。左边(红色)是项目列表,右边是另一个列表。你可以看到这些列表不完全对齐,所以它并不是一个完美的网格。我想要做的是让它像一个大列表一样,滚动任何一个列表也会滚动另一个列表。

1
为什么不将两个ListView的内容合并成一个ListView,而是试图将它们链接起来呢? - The Nail
4个回答

7

我创建了一个简单的类,基本上实现了我想要的功能。它还不够智能,不能处理第二个列表比第一个列表长或方向改变的情况,但已足以理解概念。

设置方法如下:

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

    }
}

1
抱歉,这在第二个列表滚动时无法正常工作,它禁用了底部视图,出现了许多问题。 - CoronaPintu
是的,这对我也不起作用。我的意思是,滚动链接可以工作,但新项目没有绘制在被动滚动列表上,整体效果混乱。 - Graph

0

我最终使用了这里的顶级s/o答案:Android. Scrolling 2 listviews together

拦截和重定向事件似乎比尝试对列表视图的尺寸和状态进行自己的数学计算更加优雅和一致。


0

我认为使用一个有两列的GridView更加合适,就像这样:

<GridView
    android:id="@+id/grid_view"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:numColumns="2"
    />

谢谢您的建议,但我不认为GridView能够满足我的需求。请参见我上面的编辑。 - compuguru

0
我想做的是监听左侧列表视图的滚动事件,然后通过适当的偏移量滚动右侧列表视图。以下是我的代码,我已经测试过了(非常简单,只是展示我的想法),您可以在此基础上添加您自己的代码。
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.
        }
    });

}

}

这是主要的 main.xml 布局:

<?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>

这是我的屏幕截图: 在此输入图片描述

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接