1

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().

4

2 に答える 2

2

さらに検索し、頭を掻き、脳細胞を叩いた後、次のことを思いつきました。

        lv.smoothScrollBy(-diffY, 0);

これにより、移動したい方向に違いがすぐにスクロールされます。「lv」オブジェクトが無効になり (例: 横向きから縦向きに回転)、他のリスト ビューの OnScrollListener() がリスナーを呼び出し、Activity がそれを右側のビューに渡しますが、既に無効になっているかなくなっているというクラッシュ バグが残っています。離れているため、例外が発生します。しかし、私は今それを理解することができます。

于 2012-11-07T22:34:58.323 に答える
0

これは同じアクティビティで機能します。フラグメントに適用できますか?

2 つのリストビュー位置を同期する方法

于 2013-04-23T12:01:07.057 に答える