我想收听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);
}
}
答案 0 :(得分:6)
谢谢@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);
}
}
答案 1 :(得分:0)
触摸事件从子节点传递给父节点。如果任何一个孩子消耗偶数(返回true),那么它就会停止;它没有传递给父母。所以,2个解决方案,
首先是扩展视图容器类并覆盖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.
}
}
第二种方法是设置递归设置触摸侦听所有子视图到您的自定义触摸侦听器,
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);
}
}
}