I have two fragments each containing a list view. The list view in the left fragment has a very long header view attached to it. The right fragment list view has list elements of varying height (and generally only one element that can be longer than the height of the display). The right fragment's list view is guaranteed to always be much shorter than the length (in pixels) of the left fragment's list view.
What I would like to do is, if I touch and drag/fling the left side, the right side moves roughly the same distance in the same direction as the drag/fling operation. If the right fragment's list view reaches the end (or beginning) of the list, it should just stay there. If I manipulate the right list view, it should work as usual.
As requested by sabadow, here is some code. First, left fragment:
public class LeftFragment extends SherlockFragment {
private LeftFragmentListener listener;
// The Activity must implement this interface.
public interface LeftFragmentListener {
public void syncScroll(int diffY);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
listener = (LeftFragmentListener)activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement LeftFragment.LeftFragmentListener");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment.
final ListView lv = (ListView)inflater.inflate(R.layout.main_left_fragment, container, false);
final View header = inflater.inflate(R.layout.main_left_fragment_header, null);
lv.addHeaderView(header);
... calls setAdapter, etc. ...
lv.setOnScrollListener(new OnScrollListener() {
private int lastY;
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
View c = view.getChildAt(0);
if (c != null)
{
int currY = c.getTop();
int diffY = currY - lastY;
lastY = currY;
listener.syncScroll(diffY);
}
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState != SCROLL_STATE_IDLE)
{
View c = view.getChildAt(0);
if (c != null) lastY = c.getTop();
}
}
});
return lv;
}
}
Now, Activity:
public class MainActivity extends MySlidingActivity implements LeftFragment.LeftFragmentListener {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Two list views.
setContentView(R.layout.main_two_frags);
}
@Override
public void syncScroll(int diffY) {
RightFragment f = (RightFragment)getSupportFragmentManager().findFragmentById(R.id.main_right_fragment);
if (f != null) f.execSyncScroll(diffY);
}
}
And now the right fragment:
public class RightFragment extends SherlockFragment {
private ListView lv;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment.
lv = (ListView)inflater.inflate(R.layout.main_right_fragment, container, false);
... calls setAdapter, etc. ...
return lv;
}
// Event sync across fragments - only used when the two views are showing.
public void execSyncScroll(int diffY)
{
Log.e("setSelection", "lastY + diffY = " + (lastY + diffY));
// lv.setSelectionFromTop(0, lastY + diffY);
// lv.scrollBy(0, -diffY);
// Nothing I've tried works.
}
}
The comment above where I say "Nothing I've tried works" is where I'm stuck. I have no idea what to do there to get the ListView to scroll.
scrollBy() doesn't work properly. It doesn't bound the scrolling to the scrollbar and doesn't show all items in the ListView. setSelectionFromTop() doesn't do anything at all. Using OnTouchListener and passing the MotionEvent (instead of an 'int') causes the application to crash when attempting to call lv.dispatchTouchEvent().