BNK BNK - 6 months ago 27
Android Question

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

To display data in table layout with the first column frozen, the others can scroll horizontally, I have used 2 gridviews as below XML file content:

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


and my code:

...
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) {
}
});
...


With these code, of course when I move my hand out of the screen, the
gridViewDays
gridview will have the same selection with the
gridViewID
as the image below:

enter image description here

However, when I keep my hand touch on the screen to scroll the
gridViewID
, the
gridViewDays
will look like the image below (it does not scroll while
gridViewID
is scrolling)

enter image description here

So, how can I make the
gridViewDays
gridview vertically scrolling the same as the
gridViewID
? I have also tried some methods such as
smoothScrollToPosition
,
smoothScrollByOffset
,
smoothScrollToPositionFromTop
... inside
onScroll
but they do not work

Answer

use NonScrollGridView. and wrap both in single ScrollView

Here is code for 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();
    }
}

EDIT: Here is how you can do this.

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

Now for making both headers sticky.. do following.

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

Happy Coding..