2011-01-04 7 views
2

2つの同期スクロールに関する厄介な問題があります。 異なるビュー。 私は独自のグリッドビューウィジェットを作っています。これは、グリフを使って一方向にしか表示されない "sticky"ビューを に表示します。時間が上部にあり、日付が左側にある カレンダーを考えてください。 時間を横方向にスクロールすると、日付表示はそのまま残ります。 日付を縦方向にスクロールすると は滞在する必要があります置く。Android:2つの異なるビューの同期スクロール

グリッド自体は、 の垂直スクロールビューでネストされた水平スクロールビューを使用して実装されます。グリッドはうまくいっているので、問題はありません。 スティッキビューは実際のグリッドにはないので、グリッドスクロールビューで onScrollChangedをオーバーライドし、ユーザーがグリッドをスクロールしたときにスティッキビューの scrollToをプログラムで呼び出します。

これは、2つの異なるビューがスクロールを開始してスクロールを終了するまで、わずかな時間オフセットが となることを除いて、期待どおりに機能します。あなたはスクロールが可能性が高い

すべてのビューがスクロールする図である。私が思うUIスレッド上で直線的に を実行され、私はスムーズスクロール を有効にしてsmoothScrollToを使用していることを考えるとそれ はしようとする代わりに、など、理にかなっていますこれを改善するために、同じ問題にもかかわらず です。この問題は、Samsung Galaxy Tabなどの大画面の 画面で特に顕著ですが、中小画面デバイスではほとんど となります。

ご協力いただきましてありがとうございます。簡単な修正があれば、それは新しいデザイン(上記の粘着性のあるビューの使用に合致する)を意味するならば、それはそうです。

progをトリガーするコード。それは、任意のヘルプ

のだならば、スクロール、下の水平

@Override 
protected void onScrollChanged(int x, int y, int oldx, int oldy) { 
    mListener.onScrollY(y); 
    super.onScrollChanged(x, y, oldx, oldy); 
} 
// which leads to, 
// Handle vertical scroll 
public void onScrollY(final int y) { 
    mCurrentY = y; 
    mVerticalScroll.smoothScrollTo(0, y); 
} 

XMLレイアウトの同じ、縦スクロールビューとグリッド項目に包まれた水平スクロールビューで実際のグリッドは、上下方向に追加されます
>

< com.....VerticalScrollView 
    android:id="@+id/gridscroll" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:layout_below="@id/timescroll" 
    android:layout_toRightOf="@id/vertscroll" 
    android:layout_alignTop="@id/vertscroll" 
    android:layout_marginLeft="2dp" android:scrollbars="none" 
    android:fadingEdge="none"> 

    < com....HorizScrollView 
    android:id="@+id/horizscroll" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:scrollbars="none" 
    android:fadingEdge="none"> 

    < LinearLayout android:id="@+id/grid" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:orientation="vertical"> 

     < /LinearLayout> 

     < /com.....HorizScrollView> 

     < /com.....VerticalScrollView> 

水平スティッキービューのLinearLayoutネスト

すべての

< com.....GridTimeScrollView 
    android:id="@+id/timescroller" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:scrollbars="none" 
    android:fadingEdge="none"> 

    < LinearLayout android:id="@+id/timelist" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="horizontal" /> 
    < /com.....GridTimeScrollView> 

垂直粘着性の観点

< com....GridVertListScrollView 
android:id="@+id/vertscroller" 
android:layout_width="fill_parent" 
android:layout_height="fill_parent" 
android:scrollbars="none" 
android:fadingEdge="none"> 

< LinearLayout 
android:id="@+id/vertitemlist" 
android:layout_width="fill_parent" 
android:layout_height="fill_parent" 
android:orientation="vertical" /> 
< /com.....GridVertListScrollView> 

答えて

6

まず、私はあなたがこのことを認識すべきだと思います。要するにScrollView Inside ScrollView

scrollviews内でscrollviewsを使用することは、多くの最適化を壊すという悪いことです。

今、あなたの質問に。

私はあなたの説明と同様の必要性を持っています。私はカスタムビューとそのonDrawメソッドを実装しました。これは、私が何かを描いていなかったことと、あなたがそれをする必要がないかもしれないという理由の1つにありました。とにかく

、私はあなたの最良の選択肢であると信じている:

  1. は左上、となり、「メイン」の景色と、このビューのレイアウトを作成し、相対レイアウト
  2. を拡張するカスタムビューを実装しますスクロール可能なコンポーネント
  3. は、このビューにOnGestureListenerを追加し、ジェスチャーリスナーが情事やスクロールを検出したときにカスタムビュー
  4. にあなたの活動のタッチイベントを渡し、スクロールビューのそれぞれにおけるscrollByを呼び出します。これを行うときに、トップビューを水平方向にのみスクロールする場合は、垂直スクロール距離として0を渡します。
  5. スムーズなフイングの動きを実現するには、scroller(カスタム表示)を作成する必要があります。ジェスチャーリスナーがフイングイベントを検出したら、スクロールを設定します。次に、カスタムビューのcomputeScroll()メソッドをオーバーライドし、各子ビューのスクロールを更新します。 これを確認するには、 exampleをチェックしてください。私はお詫び申し上げます、私は可能な限り良い例を投稿しようとします。 は、以下の私のコードをチェックしてください...それは簡単です:)

更新:サンプルコード

@Override 
    public void computeScroll() { 
     if (scroller.computeScrollOffset()) { 
      if (!scrolledLastFrame) { 
       lastX = scroller.getStartX(); 
       lastY = scroller.getStartY(); 
      } 

      int dx = scroller.getCurrX() - lastX; 
      int dy = scroller.getCurrY() - lastY; 

      lastX = scroller.getCurrX(); 
      lastY = scroller.getCurrY(); 

      doScroll(dx, dy); 
      scrolledLastFrame = true; 
     } else { 
      scrolledLastFrame = false; 
     } 

    } 
+0

あなたの答えをありがとう。あなたが参照する投稿は、スクロールビューとリストビューの組み合わせについて議論しているようですね。スクロールビューの入れ子はおそらく最適ではないが、最初から新しいウィジェットを必要としない唯一の選択肢のように思えた。私はこの質問に答えた前に、私はこれが私の現在のソリューションよりも "同期"されたスクロールをどう保証するのだろうか?一度に1つのビュー(グリッド、スティッキービュー)をスクロールする必要はありませんが、スクロール方法が少しずれている可能性がありますか? – Andreas

+0

No.私はあなたの "同期"問題は、スクロールに関する情報を取得したときに、すでに1つのビューで処理されているため、他のスクロールも同様にスクロールするためです。このようにして、1つのビューがスクロールし、他のビューは次のサイクルで対応するスクロールを行います。私のアプローチでは、すべてのビューが同時にスクロールします。そしてあなたはその問題を抱えません。 –

2

の回答を見てみます。なぜあなたはOnTouch Listenerでそれを扱わないのですか?タッチイベントがMOVEの場合は、コールします。

public void onScrollY(final int y) { 
    mCurrentY = y; 
    mVerticalScroll.smoothScrollTo(0, y); 
} 

他のScrollViewではgetVerticalScrollの値を使用します。それはかなり簡単です。 TouchEventsがさらに処理されるようにtrueを返します。ここで

は、それが

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    switch (event.getAction()) { 
     case MotionEvent.ACTION_MOVE: 
      lv2.onScrollY(lv.getScrollY()); 
      break; 
     default: 
      break; 
    } 
    return false; 
} 

シンプルな右のようになります。何ですか?

あなたが望むものであるかどうかは不明です。しかし、あなたが達成しようとしていることを正確に説明できますか?レイアウトの意味ではなく、実際にはあなたのUIのポイントは何ですか?

+0

ありがとうございました。これは実現可能な回避策かもしれませんが、他の理由でも別の実装を選択する必要があるようです。 – Andreas

3

smoothScrollToは使用しないでください。代わりにscrollToを使用してください。 smoothScrollToは、現在の位置から望む位置までスクロールをアニメートします。スクロールを同期させたいので、他のスクロールビューをすぐに他のスクロールビューがある場所に正確に表示したいからです。

関連する問題