7

ScrollViewを聞いて、スクロールしているかどうかを確認したいと思います。OnTouchListenerを使用しましたが、うまく機能します。しかし、OnKeyListenerを使用して、またはOnKeydownメソッドをオーバーライドして、トラックボールに互換性を追加したい場合、それは機能しません。子ボタンがフォーカスを取得すると問題が発生するようです。

この問題を解決するための解決策または回避策はありますか?どんな助けでも大歓迎です。

これが私の問題を再現するためのいくつかのデモコードです:

public class TestActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    ScrollView scrollView = (ScrollView) findViewById(R.id.scroll_view);
    LinearLayout mainLayout = (LinearLayout) findViewById(R.id.main_layout);

    LinearLayout.LayoutParams wrapParams = new LinearLayout.LayoutParams(
            ViewGroup.LayoutParams.FILL_PARENT,
            ViewGroup.LayoutParams.WRAP_CONTENT);
    for (int i = 0; i < 100; i++) {
        MyItem item = (MyItem) LayoutInflater.from(this).inflate(R.layout.item, null);
        item.setParent(scrollView);
        item.setBackgroundColor(Color.WHITE);
        item.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
                LayoutParams.WRAP_CONTENT));
        mainLayout.addView(item, wrapParams);
    }

    scrollView.setOnTouchListener(new OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            // can go into here
        }

    });

    scrollView.setOnKeyListener(new OnKeyListener() {

        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN || keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
                // never go in, unless no child button get focus
            }
            return false;
        }
    });
}

}

main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">
    <com.fannyxie.MyScroller 
        android:id="@+id/scroll_view"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:descendantFocusability="beforeDescendants"
        android:clickable="true"
        android:focusable="true">
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:orientation="vertical">
            <LinearLayout android:id="@+id/main_layout"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:orientation="vertical">
            </LinearLayout>
        </LinearLayout>
    </com.fannyxie.MyScroller>
</LinearLayout>

item.xml:

<?xml version="1.0" encoding="utf-8"?>
<com.fannyxie.MyItem xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">
    <TextView 
       android:layout_width="fill_parent"
       android:layout_height="wrap_content"
       android:text="TITLE"/>
    <Button android:layout_width="wrap_content" android:layout_height="wrap_content"
        android:id="@+id/myButton" android:text="Button"></Button>
</com.fannyxie.MyItem>

MyScroller.java

public class MyScroller extends ScrollView {

    public MyScroller(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        //not go into here...
        Log.i("MyScroller", "onKeyDown");
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onTrackballEvent(MotionEvent event) {
        //not go into here...
        Log.i("MyScroller", "onTrackballEvent");
        return super.onTrackballEvent(event);
    }

    @Override
    protected boolean onRequestFocusInDescendants(int direction,
            Rect previouslyFocusedRect) {
        //some times go into here, when no button get the focus when entering first time
        Log.i("MyScroller", "request focus in descendants");
        return super.onRequestFocusInDescendants(direction, previouslyFocusedRect);
    }



}

MyItem.java

public class MyItem extends LinearLayout {

    private Button myButton;
    public MyItem(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected boolean onRequestFocusInDescendants(int direction,
            Rect previouslyFocusedRect) {
        // never go into here
        Log.i("MyItem", "request focus in descendants");
        return super.onRequestFocusInDescendants(direction, previouslyFocusedRect);
    }

}
4

2 に答える 2

8

@Jeffreyに感謝します。しかし、私はそれを行うためのより良い方法を見つけました。ScrollViewのdispatchkeyeventメソッドをオーバーライドして、そこでトラックボール/キーボードイベントを処理するだけです。それはうまくいきます。

public class MyScroller extends ScrollView {

public MyScroller(Context context, AttributeSet attrs) {
    super(context, attrs);
}

@Override
public boolean dispatchKeyEvent(KeyEvent event) {
    if ((KeyEvent.KEYCODE_DPAD_UP == event.getKeyCode() || KeyEvent.KEYCODE_DPAD_DOWN == event.getKeyCode())) {
            //handle key events here
    }
    return super.dispatchKeyEvent(event);
}

}
于 2012-07-12T09:08:17.040 に答える
0

タッチイベントは子から親に渡されます。いずれかの子が偶数を消費する(trueを返す)場合、それは停止します。親には渡されません。だから、2つの解決策、

1つは、ビューコンテナクラスを拡張してオーバーライドすることonInterceptTouchEvent()です。これは私がそれをした例TabHostですが、あなたにとってはLinearLayout、、または何でも、

public class FlingableTabHost extends TabHost {
    private GestureDetector gestureDetector;

    public FlingableTabHost(Context context, AttributeSet attrs) {
        super(context, attrs);
        initGestureListener();
    }

    public FlingableTabHost(Context context) {
        super(context);
        initGestureListener();
    }

    public boolean onInterceptTouchEvent(MotionEvent event){
        super.onInterceptTouchEvent(event);
        // handle touch event. only return true if you handle it yourself here.
    }
}

2番目の方法は、すべての子ビューのタッチリッスンをカスタムタッチリスナーに再帰的に設定することです。

ViewGroup myLayout = ...;
registerTouchListener(myLayout, myTouchListener);

private void registerTouchListener(View view, View.OnTouchListener listener) {
  view.setOnTouchListener(listener);
  if (view instanceof ViewGroup) {
    ViewGroup vg = (ViewGroup)view;
    for (int i = 0, n = vg.getChildCount(); i < n; i++) {
      View v = vg.getChildAt(i);
      registerTouchListener(v, listener);
    }
  }
}
于 2012-07-11T17:14:51.000 に答える