如何使一个 gridview 滚动与另一个 gridview 完全相同?

How to make a gridview scrolling exactly the same as another gridview?

要在 table 布局中显示数据并冻结第一列,其他列可以水平滚动,我使用了 2 个网格视图,如下所示 XML 文件内容:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"   
    tools:context="com.example.gridviews.MainActivity">

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

        <GridView
            android:id="@+id/gridViewID"
            android:layout_width="50dp"
            android:layout_height="wrap_content"
            android:columnWidth="50dp"
            android:horizontalSpacing="1dp"
            android:numColumns="1"
            android:paddingTop="5dp"
            android:stretchMode="columnWidth"
            android:verticalSpacing="1dp" />

        <HorizontalScrollView
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal">

                <GridView
                    android:id="@+id/gridViewDays"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:columnWidth="100dp"
                    android:horizontalSpacing="1dp"
                    android:numColumns="5"
                    android:paddingTop="5dp"
                    android:scrollbarStyle="outsideOverlay"
                    android:stretchMode="columnWidth"
                    android:verticalSpacing="1dp" />

            </LinearLayout>

        </HorizontalScrollView>

    </LinearLayout>

</RelativeLayout>

和我的代码:

...
BaseAdapter adapterId = new BaseAdapter() {
    @Override
    public int getCount() {
        return dataList.size();
    }

    @Override
    public Object getItem(int position) {
        return dataList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        TextView textView = new TextView(context);
        textView.setText(String.valueOf(dataList.get(position).Id));
        textView.setLayoutParams(new GridView.LayoutParams(GridView.AUTO_FIT, 70));
        return textView;
    }
};

BaseAdapter adapterDays = new BaseAdapter() {
    @Override
    public int getCount() {
        return dataList.size() * 5;
    }

    @Override
    public Object getItem(int position) {
        return dataList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        TextView textView = new TextView(context);
        int mod = position % 5;
        int idx = position / 5;
        switch (mod) {
            case 0:
                textView.setText(String.valueOf(dataList.get(idx).Mon));
                break;
            case 1:
                textView.setText(String.valueOf(dataList.get(idx).Tue));
                break;
            case 2:
                textView.setText(String.valueOf(dataList.get(idx).Wed));
                break;
            case 3:
                textView.setText(String.valueOf(dataList.get(idx).Thu));
                break;
            case 4:
                textView.setText(String.valueOf(dataList.get(idx).Fri));
                break;
        }
        textView.setLayoutParams(new GridView.LayoutParams(GridView.AUTO_FIT, 70));
        return textView;
    }
};

gridViewID.setAdapter(adapterId);
gridViewDays.setAdapter(adapterDays);

// Horizontal scrolling of gridViewDays
LinearLayout.LayoutParams linearParams = (LinearLayout.LayoutParams) gridViewDays.getLayoutParams();
linearParams.width = 300;
gridViewDays.setLayoutParams(linearParams);

// Vertical scrolling...
gridViewID.setOnScrollListener(new AbsListView.OnScrollListener() {
    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        int firstVisibleItem = view.getFirstVisiblePosition();
        gridViewID.setSelection(firstVisibleItem);
        gridViewDays.setSelection(firstVisibleItem * 5);
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
    }
});
...

使用这些代码,当然当我将手移出屏幕时,gridViewDays gridview 将与 gridViewID 具有相同的选择,如下图所示:

但是,当我用手触摸屏幕滚动 gridViewID 时,gridViewDays 将如下图所示(在 gridViewID 滚动时它不滚动)

那么,如何使 gridViewDays gridview 垂直滚动与 gridViewID 相同?我也尝试了一些方法,例如 smoothScrollToPositionsmoothScrollByOffsetsmoothScrollToPositionFromTop... 在 onScroll 中,但它们不起作用


更新: 虽然下面的答案(@vrundpurohit 和我的)有效,但是,我发现该应用程序在处理大数据时性能不佳(我的意思是当数据列表有太多项目时)。

感谢@vrundpurohit 的评论,我在 S.O 中搜索了更多并找到了 @dennisdrew 的回答是 How to put GridView inside ScrollView

从那里开始,我使用@tacone 的 ExpandableHeightGridView class Gridview height gets cut 解决我的问题。

我修改的代码:

...
final ExpandableHeightGridView gridViewID = (ExpandableHeightGridView) findViewById(R.id.gridViewID);
final ExpandableHeightGridView gridViewDays = (ExpandableHeightGridView) findViewById(R.id.gridViewDays);

gridViewID.setExpanded(true);
gridViewDays.setExpanded(true);
...

布局文件:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.gridviews.MainActivity">

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

        <com.example.gridviews.ExpandableHeightGridView
            android:id="@+id/gridViewID"
            android:layout_width="50dp"
            android:layout_height="wrap_content"
            android:columnWidth="50dp"
            android:horizontalSpacing="1dp"
            android:numColumns="1"
            android:stretchMode="columnWidth"
            android:verticalSpacing="1dp" />

        <HorizontalScrollView
            android:id="@+id/horizontalScrollView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal">

                <com.example.gridviews.ExpandableHeightGridView
                    android:id="@+id/gridViewDays"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:columnWidth="100dp"
                    android:horizontalSpacing="1dp"
                    android:numColumns="5"
                    android:scrollbarStyle="outsideOverlay"
                    android:stretchMode="columnWidth"
                    android:verticalSpacing="1dp" />

            </LinearLayout>

        </HorizontalScrollView>

    </LinearLayout>

</ScrollView>

谢谢大家!

使用NonScrollGridView。并将两者包装在单个 ScrollView

这是 NonScrollGridView..

的代码
public class NonScrollGridView extends GridView {
    public NonScrollGridView(Context context) {
        super(context);
    }

    public NonScrollGridView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public NonScrollGridView(Context context, AttributeSet attrs,
            int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int heightMeasureSpec_custom = MeasureSpec.makeMeasureSpec(
                Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom);
        ViewGroup.LayoutParams params = getLayoutParams();
        params.height = getMeasuredHeight();
    }
}

编辑: 这是您可以执行此操作的方法。

<ScrollView android:id="@+id/scroll" ... >

    <NonScrollGridView />

    <RelativeLayout android:id="@+id/head1" ... > 
        <!-- header for 1st GridView --> 
    </RelativeLayout> 

    <HorizontalScrollView ... >

        <HorizontalScrollView ... >

            <NonScrollGridView />

             <RelativeLayout android:id="@+id/head2" ... > 
                <!-- header for 1st GridView --> 
            </RelativeLayout> 

        </HorizontalScrollView>

    </HorizontalScrollView>

</ScrollView>

现在让两者都变得 headers 粘性.. 执行以下操作。

scroll.getViewTreeObserver().addOnScrollChangedListener(
                new ViewTreeObserver.OnScrollChangedListener() {
                    public void onScrollChanged() {
                        ViewCompat.setTranslationY(head1, who.getScrollY());
                        ViewCompat.setTranslationY(head2, who.getScrollY());
                    }
                });

快乐编码..