ListView внутри прокрутки ScrollView
Я вижу некоторые вопросы о "ListView in ScrollView". И я знаю, что мы не должны делать такого гнездования, просто потому, что у обоих компонентов есть своя прокрутка, и Google сказал так (я читал, что это бесполезно). Но в моем текущем проекте мне нужно такое поведение: если listview может прокручиваться - это прокрутка, если нет (верхняя или нижняя граница списка) - прокрутка прокрутки.
Итак, я написал такой код:
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:)? Это называется часто (в движении) и на почте, может быть, это и есть причина?
Ответы
Ответ 1
Я столкнулся с такой же проблемой. Я улучшил этот код, и теперь он работает правильно, я думаю.
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);
Он прокручивается для меня довольно гладко. Надеюсь, это поможет.
Ответ 2
Если родительский элемент 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>
Ответ 3
Мой sugesstion поместил бы тег listview в сторону scrollview. И добавьте область вне списка в прокрутке. Затем поместите все в линейную компоновку. Поэтому scollview и listview будут разделены.
Ответ 4
Я думаю, вам нужно это
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;
}
});