我有两个 fragment ,每个 fragment 都包含一个 ListView 。左侧 fragment 中的 ListView 附加了一个很长的标题 View 。右 fragment ListView 具有不同高度的列表元素(通常只有一个元素可以长于显示的高度)。右侧 fragment 的 ListView 保证始终比左侧 fragment ListView 的长度(以像素为单位)短得多。
我想做的是,如果我触摸并拖动/甩动左侧,则右侧会在与拖动/甩动操作相同的方向上移动大致相同的距离。如果右侧 fragment 的 ListView 到达列表的末尾(或开始),它应该停留在那里。如果我操作正确的 ListView ,它应该照常工作。
应 sabadow 的要求,这里有一些代码。首先,左侧 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;
}
}
现在, 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);
}
}
现在是正确的 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.
}
}
我在上面的评论中说“我没有尝试过”是我被困的地方。我不知道该怎么做才能让 ListView 滚动。
scrollBy() 无法正常工作。它没有将滚动绑定(bind)到滚动条,也没有显示 ListView 中的所有项目。 setSelectionFromTop() 根本不做任何事情。使用 OnTouchListener 并传递 MotionEvent(而不是“int”)会导致应用程序在尝试调用 lv.dispatchTouchEvent() 时崩溃。
最佳答案
经过更多的搜索、摸不着头脑、猛击脑细胞,我想出了:
lv.smoothScrollBy(-diffY, 0);
这会立即向我希望的方向滚动差异。我仍然有一个崩溃错误,其中 'lv' 对象变得无效(例如,将横向旋转为纵向)并且另一个 ListView 的 OnScrollListener() 调用监听器,Activity 将它传递给右 View 但它已经变得无效或消失离开,因此引发异常。但我现在可以弄明白了。
关于android - 如何在各自的 fragment 中同步两个不同 ListView 的滚动距离?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13277160/