Улучшение прокрутки в ListView внутри ScrollView - PullRequest
1 голос
/ 02 августа 2011

Я вижу некоторые вопросы о проблеме «ListView inside ScrollView».И я знаю, что мы не должны делать такое вложение, просто потому, что оба компонента имеют собственную прокрутку, и Google сказал так (я читал, что это бесполезная вещь).Но в моем текущем проекте мне нужно такое поведение: если просмотр списка может прокручиваться - это прокрутка, если нет (верхняя или нижняя граница списка) - прокрутка прокручивается.Итак, я написал такой код:

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 :)?Он вызывается часто (на ходу) и на почте, может, в этом причина?

Ответы [ 4 ]

3 голосов
/ 25 апреля 2014

Я столкнулся с той же проблемой.Я улучшил этот код, и теперь он работает правильно, я думаю.

    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;
        }
    });
}

Когда мы касаемся просмотра списка - мы включаем его прокрутку и отключаем родительскую прокрутку:

                    scroll.requestDisallowInterceptTouchEvent(true);
                    list.requestDisallowInterceptTouchEvent(false);

И если мы достигаемграница списка - мы отключаем его прокрутку и включаем родительскую прокрутку:

                    scroll.requestDisallowInterceptTouchEvent(false);
                    list.requestDisallowInterceptTouchEvent(true);

Для меня это довольно плавно.Надеюсь, это поможет.

1 голос
/ 09 апреля 2012

Если родителем является 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>
0 голосов
/ 19 июля 2013

Я думаю, тебе нужно это

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;
            }
        });
0 голосов
/ 27 августа 2011

Мой sugesstion разместил бы тег listview вне прокрутки.И добавить область за пределами списка внутри прокрутки.Тогда поместите все в линейную схему.Таким образом, scollview и listview будут разделены.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...