Android. Прокрутка 2 списков вместе

Это тоже может помочь.

# mysqldump -u root -p database0 > /tmp/database0.sql
# mysql -u root -p -e 'create database database0_bkp'
# mysql -u root -p database0_bkp < /tmp/database0.sql
# mysql -u root -p database0 -e 'insert into database0.table_you_want select * from database0_bkp.table_you_want'
23
задан s1ni5t3r 9 September 2012 в 19:54
поделиться

5 ответов

OK. У меня есть ответ сейчас. Проблема в том, что .setSelectionFromTop () будет работать только в том случае, если представление списка было в верхнем макете (то есть не вложено). После некоторого расчесывания головы я понял, что могу сделать свой макет RelativeLayout и получить тот же внешний вид, но без необходимости вложения макетов для флажка и списка. Это новый макет:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/recordViewLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">

        <CheckBox android:id="@+id/checkBoxTop"
            android:text="Check All"
            android:layout_width="160dp"
            android:layout_height="wrap_content"/>"


        <ListView android:id="@+id/engNameList"
            android:layout_width="160dp"
            android:layout_height="wrap_content"
            android:layout_below="@+id/checkBoxTop"/>       





        <HorizontalScrollView  
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@+id/checkBoxTop">

            <LinearLayout android:id="@+id/scroll"  
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <include layout="@layout/record_view_line" android:id="@+id/titleLine" />

                <ListView 
                    android:id="@android:id/list"
                    android:layout_height="wrap_content"
                    android:layout_width="match_parent"/>

            </LinearLayout>

        </HorizontalScrollView>
    </RelativeLayout>

Это в основном код, который идет с макетом.

В onCreate ()

    engListView=getListView();
    engListView.setOnTouchListener(this);


    recordListView=(ListView)findViewById(R.id.recordList);
    recordListView.setOnScrollListener(this);

и методах прослушивания:

public boolean onTouch(View arg0, MotionEvent event) {
    recordListView.dispatchTouchEvent(event);

    return false;
}


public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
    View v=view.getChildAt(0);
    if(v != null)
        engListView.setSelectionFromTop(firstVisibleItem, v.getTop());
}
6
ответ дан s1ni5t3r 9 September 2012 в 19:54
поделиться

Переписать

Мне не особо повезло с передачей действий прокрутки в одном ListView к другому. Поэтому я выбрал другой метод: прохождение MotionEvent. Это позволяет каждому ListView вычислять свою собственную плавную прокрутку, быструю прокрутку или что-либо еще.

Во-первых, нам понадобятся некоторые переменные класса:

ListView listView;
ListView listView2;

View clickSource;
View touchSource;

int offset = 0;

Каждый метод, который я добавлю в listView, будет почти идентичен для listView2, единственная разница что listView2 будет ссылаться на listView (не на себя). Я не включил повторяющийся код listView2.

Во-вторых, давайте начнем с OnTouchListener:

listView = (ListView) findViewById(R.id.engNameList);
listView.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if(touchSource == null)
            touchSource = v;

        if(v == touchSource) {
            listView2.dispatchTouchEvent(event);
            if(event.getAction() == MotionEvent.ACTION_UP) {
                clickSource = v;
                touchSource = null;
            }
        }

        return false;
    }
});

Чтобы предотвратить циклическую логику: listView вызовов listView2 вызовов listView вызовов ... Я использовал класс переменная touchSource, чтобы определить, когда должно быть передано MotionEvent. Я предположил, что вы не хотите, чтобы щелчок строки в listView также щелкал в listView2, поэтому я использовал другую переменную класса clickSource, чтобы предотвратить это.

В-третьих, OnItemClickListener:

listView.setOnItemClickListener(new OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        if(parent == clickSource) {
            // Do something with the ListView was clicked
        }
    }
});

В-четвертых, прохождение каждого события касания не является идеальным, поскольку появляются случайные расхождения. OnScrollListener идеально подходит для устранения этих проблем:

listView.setOnScrollListener(new OnScrollListener() {
    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        if(view == clickSource) 
            listView2.setSelectionFromTop(firstVisibleItem, view.getChildAt(0).getTop() + offset);
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {}
});

(Необязательно) Наконец, вы упомянули, что у вас возникли проблемы, поскольку listView и listView2 начинаются на разных высотах в макете. Я настоятельно рекомендую изменить макет, чтобы сбалансировать ListViews, но я нашел способ решить эту проблему. Однако это немного сложно.
Вы не можете рассчитать разницу в высоте между двумя макетами до тех пор, пока не будет визуализирован весь макет, но для этого момента обратного вызова нет ... поэтому я использую простой обработчик:

Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        // Set listView's x, y coordinates in loc[0], loc[1]
        int[] loc = new int[2];
        listView.getLocationInWindow(loc);

        // Save listView's y and get listView2's coordinates
        int firstY = loc[1];
        listView2.getLocationInWindow(loc);

        offset = firstY - loc[1];
        //Log.v("Example", "offset: " + offset + " = " + firstY + " + " + loc[1]);
    }
};

I предположим , что задержка в полсекунды достаточно велика для визуализации макета и запуска таймера в onResume():

handler.sendEmptyMessageDelayed(0, 500);

Если вы используете смещение, я хочу пояснить, что listView2 Метод OnScroll вычитает смещение, а не добавляет его:

listView2.setSelectionFromTop(firstVisibleItem, view.getChildAt(0).getTop() - offset);

Надеюсь, это поможет!

34
ответ дан Sam 9 September 2012 в 19:54
поделиться

Я разрешаю это путем изменения ListView на RecyclerView, использую RecyclerView .addOnScrollListener для синхронизации события прокрутки. И нет никаких расхождений, это идеально!

private void syncScrollEvent(RecyclerView leftList, RecyclerView rightList) {

    leftList.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            return rightList.getScrollState() != RecyclerView.SCROLL_STATE_IDLE;
        }
    });
    rightList.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            return leftList.getScrollState() != RecyclerView.SCROLL_STATE_IDLE;
        }
    });


    leftList.addOnScrollListener(new RecyclerView.OnScrollListener() {

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
             if (recyclerView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE) {
                 rightList.scrollBy(dx, dy);
            }
        }
    });
    rightList.addOnScrollListener(new RecyclerView.OnScrollListener() {
         @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            if (recyclerView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE) {
                leftList.scrollBy(dx, dy);
            }
        }
    });

}
2
ответ дан Peng Lin 9 September 2012 в 19:54
поделиться

В соответствии с инструкциями Сэма я разработал простое приложение, показывающее прокрутку двух списков вместе. На самом деле моей главной целью является создание горизонтально прокручиваемого расширяемого списка с фиксированными / замороженными столбцами, и работа над ним, когда он будет завершен, скоро предоставит к нему доступ https://github.com/huseyinDaVinci/Android/tree/master/FrozenListViews

1
ответ дан huseyin 9 September 2012 в 19:54
поделиться

Попробуйте приведенное ниже решение, оно работает в моем случае

leftlist.setOnScrollListener(new SyncedScrollListener(rightlist));
rightlist.setOnScrollListener(new SyncedScrollListener(leftlist));

SyncedScrollListener.java

package com.xorbix.util;

import android.view.View;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;

public class SyncedScrollListener implements OnScrollListener{
    int offset;
    int oldVisibleItem = -1;
    int currentHeight;
    int prevHeight;
    private View mSyncedView;


    public SyncedScrollListener(View syncedView){

        if(syncedView == null){
            throw new IllegalArgumentException("syncedView is null");
        }

        mSyncedView = syncedView;
    }

    public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) {

        int[] location = new int[2];

        if(visibleItemCount == 0){
            return;
        }

        if(oldVisibleItem != firstVisibleItem){

            if(oldVisibleItem < firstVisibleItem){
                prevHeight = currentHeight;
                currentHeight = view.getChildAt(0).getHeight();

                offset += prevHeight;

            }else{
                currentHeight = view.getChildAt(0).getHeight();

                View prevView;
                if((prevView = view.getChildAt(firstVisibleItem - 1)) != null){
                    prevHeight = prevView.getHeight();
                }else{
                    prevHeight = 0;
                }

                offset -= currentHeight;
            }

            oldVisibleItem = firstVisibleItem;
        }

        view.getLocationOnScreen(location);
        int listContainerPosition = location[1];

        view.getChildAt(0).getLocationOnScreen(location);
        int currentLocation = location[1];

        int blah = listContainerPosition - currentLocation + offset;

        mSyncedView.scrollTo(0, blah);

    }

    public void onScrollStateChanged(AbsListView view, int scrollState) {
        // TODO Auto-generated method stub

    }
}
0
ответ дан Rhn Bhadani 9 September 2012 в 19:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: