5

スクロール前: ここに画像の説明を入力

スクロール中: ここに画像の説明を入力

スクロール中に期待すること: ここに画像の説明を入力

Horizo​​ntalScrollView に問題があります。このビューから要素を選択すると、次のように呼び出してその要素にフォーカスを設定します。

else if (v.getParent() == candidatesScrollView.getChildAt(0))
{
    Button candidateButton = (Button) v;
    v.requestFocusFromTouch();
    v.setSelected(true);
            (...)
}

その後、他の要素を選択せず​​にリストをスクロールすると、以前に選択した要素のフォーカスが失われます。このトピックについていくつか調査しましたが、うまくいく解決策はありませんでした...選択した要素からフォーカスを失うことなく、Horizo​​ntalScrollList をスクロールするにはどうすればよいですか? どんな助けでも大歓迎です。その質問をしてから約 14 日が経過しましたが、まだ解決策が見つかりません。助けてください。

ここに私のXMLの一部があります:

<HorizontalScrollView
        android:id="@+id/CandidatesHorizontalScrollView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@+id/linearLayout2"
        android:clickable="false"
        android:focusable="false"
        android:focusableInTouchMode="false"
        android:visibility="gone" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clickable="false"
        android:focusable="false"
        android:focusableInTouchMode="false"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/horizontalscrollview1_button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textSize="25sp" />

        (...)
        // 11 more buttons
    </LinearLayout>

</HorizontalScrollView>

アップデート

私の現在の解決策#1(正しく機能しない): スクロールしてから再度スクロールすると(たとえば、スクロールバック)、選択した要素からスクロールが開始されます。

onTouchEvent() メソッドをオーバーライドするカスタム Horizo​​ntalScrollView クラスを作成しました。その場合、1ピクセルでも移動するたびに計算を行う必要があるため、これが最適な方法だとは思いません。たとえば、以下のメソッドに toast.show() を追加すると、移動したピクセルと同じ数のトーストを表示しようとします (10 ピクセル移動すると、10 個のトーストを表示しようとします)。とにかく、それは私にとってはうまくいき、選択と集中が保たれています.

このコードを修正して、最終的にその既知の問題に対する適切な回答を作成するのを手伝ってください:

@Override
public boolean onTouchEvent(MotionEvent ev)
{
    int i = 0;
    Button button = null;
    for (; i < 11; i++)
    {
        button = (Button)((LinearLayout)getChildAt(0)).getChildAt(i);
        if(button.isSelected())
            break;
    }
    super.onTouchEvent(ev);
    button.setSelected(true);
    button.requestFocusFromTouch();

    return true;
}

上記のコードが機能することを確認するには、Horizo​​ntalScrollView で一度に 1 つの項目のみを選択する必要があります。つまり、別のボタンを押したときに、前の項目を setSelected(false) にする必要があります。

私の現在の解決策#2(正しく機能していません):

私が実装しようとした解決策 #2 は、最初の解決策が十分に洗練されていないと考えて、ジェスチャー検出器の使用を伴います。カスタム Horizo​​ntalListView クラスに、次のコードを追加しました。

コンストラクタ:

public MyHorizontalScrollView(Context context, AttributeSet attrs) {
    super(context, attrs);
    this.context = context;
    gestureDetector = new GestureDetector(context, new MyHorizontalScrollViewGestureDetector());
    this.setOnTouchListener(new OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            gestureDetector.onTouchEvent(event);

            return true;
        }
    });
    // TODO Auto-generated constructor stub
}

MyHorizo​​ntalScrollViewGestureDetector 内部クラス:

public class MyHorizontalScrollViewGestureDetector extends SimpleOnGestureListener
    {

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
        {
            //Here code similar like that one in solution #1
            //But the View is not scrolling, even without that code 
            super.onScroll(e1, e2, distanceX, distanceY);

            return true; 
        }
    }   

ただし、そのソリューションではリストがスクロールしません。onScroll メソッドに追加できます。

ScrollBy((int)positionX, (int)positionY);

これにより、リストがスクロールしますが、良い方法ではなく、時々フリーズします。なぜスクロールがスーパーによって呼び出されないのか疑問に思っています。方法。

私の現在の解決策#3(機能していますが、ウォークアラウンドです):

解決策 1 と 2 の両方がうまくいかなかったので、私はもうフォーカスを当てないことにしました。私が今やっていることは、クリックするたびに、そして別のボタンに変更するたびに、Button Drawable を変更することです。フォーカス ボタン (Holo) と同じ Drawable を使用します。その場合、Horizo​​ntalScrollView でのスクロールについては心配する必要はありません。この解決策はある種のウォークアラウンドであるため、コメント、提案、編集をお待ちしています。

4

4 に答える 4

1

次の解決策を適用できますか (ここからアイデアを取り入れました):

関数を拡張HorizontalScrollViewしてオーバーライドする独自のカスタム クラスを作成してみてください。onScrollChanged()

public class TestHorizontalScrollView extends HorizontalScrollView {

    public TestHorizontalScrollView(Context context) {
        super(context);
    }


    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        // TODO Auto-generated method stub
        Log.i("Scrolling", "X from ["+oldl+"] to ["+l+"]");
        Button button = null;
        for (; i < 11; i++)
        {
          button = (Button)((LinearLayout)getChildAt(0)).getChildAt(i);
          if(button.isSelected())
            break;
        }
        button.setSelected(true);
        button.requestFocusFromTouch();

        super.onScrollChanged(l, t, oldl, oldt);
    }

}

スクロールを検出したので ( の 1 つについて話しているHorizontalScrollView)、対応するボタンの選択状態を再度設定できます。この解決策を試してみて、うまくいくかどうかを確認してください。質問も非常に興味深いので、私はこれの解決に非常に興味があります。

ともあれ、なんとか以下の記事を見つけました。彼らはそこで次のように述べています。

テキスト項目のリストを表示する単純なアプリケーション、たとえば ApiDemos を想像してみてください。ユーザーは、トラックボールを使用してリストを自由にナビゲートでき、指を使用してリストをスクロールおよびフリングすることもできます。このシナリオの問題は選択です。リストの一番上にあるアイテムを選択し、リストを一番下に移動すると、選択はどうなりますか? アイテムに残して画面からスクロールする必要がありますか? この場合、選択範囲をトラックボールで移動するとどうなりますか? さらに悪いことに、トラックボールを押して、現在選択されているアイテムを操作すると、画面に表示されなくなります。慎重に検討した結果、選択を完全に削除することにしました。

タッチ モードでは、フォーカスも選択もありません。グリッド内のリストで選択された項目は、ユーザーがタッチ モードに入るとすぐに選択解除されます。同様に、ユーザーがタッチ モードに入ると、フォーカスされたウィジェットはフォーカスされなくなります。下の画像は、ユーザーがトラックボールでアイテムを選択した後にリストをタッチするとどうなるかを示しています。

とにかく、そこにある声明は私を喜ばせなかったので、さらにこれを見つけました:

android:focusable="true"
android:focusableInTouchMode="true"

も設定android:clickable="true"します ( を設定android:focusable="true"することもできますLinearLayout)。

それらをボタンとそれらを含むレイアウトに追加してみてください。すべてを試してください。

全力でバックアップしていきます。

乾杯

于 2013-07-03T14:52:49.507 に答える
0

この質問には、ドローアブルの変更などを既に行っている可能性があるため、カスタムの方法以外には答えがありません。理由は、スライドすると、フォーカスが Horizo​​ntalScroll に移動し、1 つの項目にしかフォーカスできないためです。複数のビューにフォーカスするのは意味がありません。したがって、drawable を実装するか (これは行ったようです)、チェックボックスを拡張して機能をオーバーライドし、フォーカスされたときにチェックされて外観が変更されるようにします。

于 2013-07-08T23:36:59.060 に答える
0

私は自分の問題の解決策を見つけました。詳細については、更新された質問をご覧ください。基本的に、フォーカスを使用する代わりに、はるかに簡単な Drawable セレクターを使用することにしました。

于 2013-07-11T01:22:49.057 に答える
0

あなたが抱えている問題と似ていると思うスクロールビューの問題を覚えています。

私が思いついた解決策は、クラスのonRequestFocusInDescendantsメソッドをオーバーライドすることでした。まだ作成していない場合は、HorizontalScrollView拡張された独自のクラスを作成する必要があります。HorizontalScrollView

私の場合、メソッドから常に true を返しました。これは、フォーカスの変更を処理したことを呼び出し元に伝え、それ以上何もしようとしないようにします。

@Override
protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
  return true;
}

要件によっては、特定の条件下 (スクロールが進行中など) でのみ true を返す必要がある場合があり、それ以外の場合は呼び出しをスーパークラスに転送します。

于 2013-07-07T23:23:47.607 に答える