我可以看到有关“ScrollView中的ListView”问题的一些问题。我知道,我们不应该做这样的嵌套,只是因为两个组件都有自己的滚动而谷歌这么说(我读过它是没用的东西)。但是在我当前的项目中我需要这样的行为:如果listview可以滚动 - 它是滚动,如果不滚动(listview的顶部或底部边框) - scrollview正在滚动。 所以,我写了这样的代码:
public static void smartScroll(final ScrollView scroll, final ListView list){
scroll.requestDisallowInterceptTouchEvent(true);
list.setOnTouchListener(new OnTouchListener() {
private boolean isListTop = false, isListBottom = false;
private float delta = 0, oldY = 0;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
oldY = event.getY();
break;
case MotionEvent.ACTION_UP:
delta = 0;
break;
case MotionEvent.ACTION_MOVE:
delta = event.getY() - oldY;
oldY = event.getY();
isListTop = false;
isListBottom = false;
View first = list.getChildAt(0);
View last = list.getChildAt(list.getChildCount()-1);
if(first != null && list.getFirstVisiblePosition() == 0 && first.getTop() == 0 && delta > 0.0f){
isListTop = true;
}
if(last != null && list.getLastVisiblePosition() == list.getCount()-1 && last.getBottom() <= list.getHeight() && delta < 0.0f){
isListBottom = true;
}
if( (isListTop && delta > 0.0f) || (isListBottom && delta < 0.0f) ){
scroll.post(new Runnable() {
public void run() {
scroll.smoothScrollBy(0, -(int)delta);
}
});
}
break;
default: break;
}
scroll.requestDisallowInterceptTouchEvent(true);
return false;
}
});
}
它起作用,至少在目标API 8上。但是有一些滚动故障(不自然的跳转)。我认为,scroll.smoothScrollBy(0, - (int)delta)中的原因;有任何想法,如何改进scrollview滚动:)?经常(在移动中)和在帖子上调用它,也许这就是原因?
答案 0 :(得分:3)
我遇到了同样的问题。我已经改进了这段代码,现在它的工作正常我认为。
public static void smartScroll(final ScrollView scroll, final ListView list){
list.setOnTouchListener(new View.OnTouchListener() {
private boolean isListTop = false, isListBottom = false;
private float delta = 0, oldY = 0;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
scroll.requestDisallowInterceptTouchEvent(true);
list.requestDisallowInterceptTouchEvent(false);
oldY = event.getY();
break;
case MotionEvent.ACTION_UP:
delta = 0;
break;
case MotionEvent.ACTION_MOVE:
delta = event.getY() - oldY;
oldY = event.getY();
isListTop = false;
isListBottom = false;
View first = list.getChildAt(0);
View last = list.getChildAt(list.getChildCount()-1);
if(first != null && list.getFirstVisiblePosition() == 0 && first.getTop() == 0 && delta > 0.0f){
isListTop = true;
}
if(last != null && list.getLastVisiblePosition() == list.getCount()-1 && last.getBottom() <= list.getHeight() && delta < 0.0f){
isListBottom = true;
}
if( (isListTop && delta > 0.0f) || (isListBottom && delta < 0.0f) ){
scroll.requestDisallowInterceptTouchEvent(false);
list.requestDisallowInterceptTouchEvent(true);
}
break;
default: break;
}
return false;
}
});
}
当我们触摸listview时 - 我们启用它的滚动并禁用父滚动:
scroll.requestDisallowInterceptTouchEvent(true);
list.requestDisallowInterceptTouchEvent(false);
如果我们到达列表的边界 - 我们禁用其滚动并启用父滚动:
scroll.requestDisallowInterceptTouchEvent(false);
list.requestDisallowInterceptTouchEvent(true);
它对我来说非常流畅。希望这会有所帮助。
答案 1 :(得分:1)
如果父级是ScrollView,请将其更改为LinearLayout。它会工作。例如,在这里我写了LinearLayout而不是ScrollView。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/scroll"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true">
<ListView android:id="@+id/fontlistView"
android:scrollbars="vertical"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_gravity="center_horizontal"
android:scrollbarAlwaysDrawVerticalTrack="true">
</ListView>
</LinearLayout>
答案 2 :(得分:0)
我的sugesstion会将listview标记放在scrollview的旁边。并在scrollview中添加listview外的区域。然后将所有内容放在线性布局中。所以scollview和listview将分开。
答案 3 :(得分:0)
我想你需要这个
listview = (ListView) findViewById(R.id.search_list);
listview.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
v.getParent().requestDisallowInterceptTouchEvent(true);
} else if (event.getAction() == MotionEvent.ACTION_UP) {
v.getParent().requestDisallowInterceptTouchEvent(false);
}
return false;
}
});