Android。2つのリストビューを同時にスクロールする 質問する

Android。2つのリストビューを同時にスクロールする 質問する

わかりました。私が実現しようとしているのは、Excel の固定ペインと同じ効果を実現するレイアウトです。つまり、メインの ListView とともに水平にスクロールするヘッダー行と、メインの ListView とともに垂直にスクロールする左側の ListView が必要です。ヘッダー行と左側のリストビューは、他の次元でスクロールするときには静止したままである必要があります。

XML レイアウトは次のとおりです。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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">
    <LinearLayout android:layout_width="160dp"
        android:layout_height="match_parent"
        android:orientation="vertical">

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


    <HorizontalScrollView  
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <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>
</LinearLayout>

次に、ListActivityでこのコードを使用します

public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
    View v = recordsListView.getChildAt(0);
    int top = (v == null) ? 0 : v.getTop();

((ListView)findViewById(R.id.engNameList)).setSelectionFromTop(firstVisibleItem, top);      
}

これにより、ユーザーが右側の ListView をスクロールすると、左側の ListView もスクロールするはずです。残念ながら、そうはなりません。

グーグルで少し調べてみたところ、setSelectionFromTop() 関数は、複数のレイアウト内にネストされた ListView では機能しないようです。

このような場合、一緒にスクロールする方法、レイアウトを設定する別の方法、またはまったく別のテクニックを提案できる人はいますか。

ベストアンサー1

リライト

ある ListView のスクロール アクションを別の ListView に渡すことはあまりうまくいきませんでした。そこで、 を渡すという別の方法を選択しました。これにより、それぞれが独自のスムーズ スクロール、高速スクロール、その他の計算を実行できるMotionEventようになります。ListView

初め、いくつかのクラス変数が必要になります:

ListView listView;
ListView listView2;

View clickSource;
View touchSource;

int offset = 0;

に追加するすべてのメソッドはlistViewとほぼ同じになりますがlistView2、唯一の違いは が(それ自体ではなく)listView2を参照することですlistView。繰り返しコードは含めませんでしたlistView2

2番、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クラス変数を使用しました。行のクリックが 内でもクリックされることは望ましくないと思われるため、これを防ぐために別のクラス変数を使用しました。touchSourceMotionEventlistViewlistView2clickSource

三番目、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
        }
    }
});

第4、すべてのタッチ イベントを渡すのは、不一致が時々発生するため完璧ではありません。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非常にListView のバランスをとるためにレイアウトを変更することを推奨しますが、私はこれに対処する方法を見つけました。ただし、少しトリッキーです。
レイアウト全体がレンダリングされるまで、2 つのレイアウト間の高さの差を計算することはできませんが、この時点ではコールバックはありません... そのため、単純なハンドラーを使用します。

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

仮定するレイアウトをレンダリングしてタイマーを開始するには、0.5 秒の遅延で十分ですonResume()

handler.sendEmptyMessageDelayed(0, 500);

オフセットを使用する場合、listView2OnScroll メソッドはオフセットを追加するのではなく、減算することを明確にしておきます。

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

お役に立てれば幸いです!

おすすめ記事