5

我尝试按照这篇文章Synchronize ScrollView 滚动位置 - android的建议进行操作, 但遇到了问题。

背景 - 我想要一个具有水平和垂直滚动的表格布局,但我希望第一行和第一列始终存在 - 就像 excel 的冻结窗格一样。不幸的是,Android java编程似乎几乎是不可能的……让我很头疼。我已经设置好了,如果我可以同步这两个水平滚动视图,那么我会让表格按照我想要的方式工作。

我遵循了上面发布的链接中的建议,我遇到的问题就是这个。当我实现应用程序强制关闭

scrollView1.setScrollViewListener(this);

我认为问题可能是我声明 ObservableScrollViews 的方式。我没有使用 XML - 所有对象都是以编程方式创建的。我尝试使用

private ObservableScrollView oScrollViewOne = new ObservableScrollView (this);

但这也会导致关闭力。(我可以创建一个常规滚动视图,为其分配一个 ID,然后使用

scrollView1 = (ObservableScrollView) findViewById(ID); 其中 ID 是我给滚动视图的整数。

如果我不使用 XML 布局,我想知道如何处理下面的评论以及如何使用它们。

我们应该在布局中指定这个新的 ObservableScrollView 类,而不是现有的 ScrollView 标签。

com.test.ObservableScrollView android:id="@+id/scrollview1" ...

使用显式代码实现两个水平滚动视图同步的任何其他建议 - 不仅仅是使用 OnTouchMotionEvent 或其他想法而不提供代码的建议,正如我之前所见。

这是错误代码

10-23 23:33:08.631: ERROR/AndroidRuntime(18187): FATAL EXCEPTION: main
10-23 23:33:08.631: ERROR/AndroidRuntime(18187): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.glen.apps.TeacherAidePro/com.glen.apps.TeacherAidePro.TeacherAidePro}: java.lang.NullPointerException
10-23 23:33:08.631: ERROR/AndroidRuntime(18187):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2709)
10-23 23:33:08.631: ERROR/AndroidRuntime(18187):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2803)
10-23 23:33:08.631: ERROR/AndroidRuntime(18187):     at android.app.ActivityThread.access$2300(ActivityThread.java:135)
10-23 23:33:08.631: ERROR/AndroidRuntime(18187):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2136)
10-23 23:33:08.631: ERROR/AndroidRuntime(18187):     at android.os.Handler.dispatchMessage(Handler.java:99)
10-23 23:33:08.631: ERROR/AndroidRuntime(18187):     at android.os.Looper.loop(Looper.java:144)
10-23 23:33:08.631: ERROR/AndroidRuntime(18187):     at android.app.ActivityThread.main(ActivityThread.java:4937)
10-23 23:33:08.631: ERROR/AndroidRuntime(18187):     at java.lang.reflect.Method.invokeNative(Native Method)
10-23 23:33:08.631: ERROR/AndroidRuntime(18187):     at java.lang.reflect.Method.invoke(Method.java:521)
10-23 23:33:08.631: ERROR/AndroidRuntime(18187):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
10-23 23:33:08.631: ERROR/AndroidRuntime(18187):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
10-23 23:33:08.631: ERROR/AndroidRuntime(18187):     at dalvik.system.NativeStart.main(Native Method)
10-23 23:33:08.631: ERROR/AndroidRuntime(18187): Caused by: java.lang.NullPointerException
10-23 23:33:08.631: ERROR/AndroidRuntime(18187):     at android.content.ContextWrapper.getResources(ContextWrapper.java:80)
10-23 23:33:08.631: ERROR/AndroidRuntime(18187):     at android.view.View.<init>(View.java:1810)
10-23 23:33:08.631: ERROR/AndroidRuntime(18187):     at android.view.View.<init>(View.java:1856)
10-23 23:33:08.631: ERROR/AndroidRuntime(18187):     at android.view.ViewGroup.<init>(ViewGroup.java:299)
10-23 23:33:08.631: ERROR/AndroidRuntime(18187):     at android.widget.FrameLayout.<init>(FrameLayout.java:83)
10-23 23:33:08.631: ERROR/AndroidRuntime(18187):     at android.widget.ScrollView.<init>(ScrollView.java:137)
10-23 23:33:08.631: ERROR/AndroidRuntime(18187):     at android.widget.ScrollView.<init>(ScrollView.java:133)
10-23 23:33:08.631: ERROR/AndroidRuntime(18187):     at android.widget.ScrollView.<init>(ScrollView.java:129)
10-23 23:33:08.631: ERROR/AndroidRuntime(18187):     at com.glen.apps.TeacherAidePro.ObservableScrollView.<init>(ObservableScrollView.java:12)
10-23 23:33:08.631: ERROR/AndroidRuntime(18187):     at com.glen.apps.TeacherAidePro.TeacherAidePro.<init>(TeacherAidePro.java:119)
10-23 23:33:08.631: ERROR/AndroidRuntime(18187):     at java.lang.Class.newInstanceImpl(Native Method)
10-23 23:33:08.631: ERROR/AndroidRuntime(18187):     at java.lang.Class.newInstance(Class.java:1429)
10-23 23:33:08.631: ERROR/AndroidRuntime(18187):     at android.app.Instrumentation.newActivity(Instrumentation.java:1036)
10-23 23:33:08.631: ERROR/AndroidRuntime(18187):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2701)
10-23 23:33:08.631: ERROR/AndroidRuntime(18187):     ... 11 more

这是第 12 行

 1. package com.glen.apps.TeacherAidePro;
 2.
 3. import android.content.Context;
 4. import android.util.AttributeSet;
 5. import android.widget.ScrollView;
 6.
 7. public class ObservableScrollView extends ScrollView {
 8.
 9.   private IScrollListener listener = null;    
10.
11.   public ObservableScrollView(Context context) {
12.       super(context);
  }
4

2 回答 2

6

错误指向 ObservableScrollView 的构造函数中的空指针。您能否单独发布构造函数以及第 12 行?

我在您的 XML 和自定义滚动视图交互方式中看到的一个可能问题是您的自定义滚动视图是一个内部类。请参阅此页面了解如何在 XML 中声明内部类自定义组件,或将其移动到外部类。我通常把它放在一个外部类中,但如果你想把它作为一个内部类,它会像

<view
    class="com.glen.apps.TeacherAidePro$ObservableScrollView"
.../>

我不认为这解释了你的空指针异常,所以请发布你的 ObservableScrollView 类。

编辑:

如果你坚持用 Java 做所有事情,这里有一个工作示例:

private ObservableScrollView scrollView1 = null;
private ObservableScrollView scrollView2 = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    LinearLayout parent = new LinearLayout(this);
    parent.setOrientation(LinearLayout.HORIZONTAL);
    parent.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
            LayoutParams.FILL_PARENT));
    parent.setWeightSum(2.0f);

    scrollView1 = new ObservableScrollView(this);
    scrollView1.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
            LayoutParams.FILL_PARENT, 1.0f));
    scrollView2 = new ObservableScrollView(this);
    scrollView2.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
            LayoutParams.FILL_PARENT, 1.0f));

    scrollView1.setScrollViewListener(new ScrollViewListener() {
        public void onScrollChanged(ObservableScrollView scrollView, int x,
                int y, int oldx, int oldy) {
            scrollView2.scrollTo(x, y);
        }
    });
    scrollView2.setScrollViewListener(new ScrollViewListener() {
        public void onScrollChanged(ObservableScrollView scrollView, int x,
                int y, int oldx, int oldy) {
            scrollView1.scrollTo(x, y);
        }
    });

    TextView tv1 = new TextView(this);
    tv1.setText("TEXT1TEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXT");
    tv1.setTextSize(36.0f);
    scrollView1.addView(tv1);

    TextView tv2 = new TextView(this);
    tv2.setText("TEXT2TEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXT");
    tv2.setTextSize(36.0f);
    scrollView2.addView(tv2);

    parent.addView(scrollView1);
    parent.addView(scrollView2);
    parent.invalidate();

    setContentView(parent);
}

基本上,这会并排创建两个滚动视图,每个视图的权重为 1.0,并将它们放在一个 LinearLayout 中,布局上的总权重为 2.0,因此它们每个都获得一半的宽度。

但是,我强烈建议您习惯 XML,因为创建布局要容易得多(在我看来)。它也更容易发现错误,并且 XML 的嵌套形式使其更易于阅读。无论如何,希望这能解决问题。

于 2011-10-24T12:24:23.910 回答
1

这是我在代码中的解决方案进一步解释:

//This should be inside yout oncreate
syncScrolls(firstView, secondView;
        syncScrolls(secondView, firstView);




    //This method accept 2 horizontal scroll views, but you could improve it passing an array. 
        private void syncScrolls(final HorizontalScrollView currentView, final HorizontalScrollView otherView) {

//This create the Gesture Listener where we override the methods we need
                GestureDetector.SimpleOnGestureListener gestureListener = new GestureDetector.SimpleOnGestureListener() {
                    @Override
                    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
//Here onfling just return true, this way doesnt happens
                        return true;
                    }
                    @Override
                    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
//On scroll we sync the movement of the both views
                        otherView.scrollTo(currentView.getScrollX(), 0);
                        return super.onScroll(e1, e2, distanceX, distanceY);
                    }
                    @Override
                    public boolean onDown(MotionEvent e) {
                        return true;
                    }
                };
        //This create the gesture detectors that implements the previous custom gesture listener
                final GestureDetector gestureDetector = new GestureDetector(this, gestureListener);
        //And finally we set everything to the views we need
                currentView.setOnTouchListener(new View.OnTouchListener() {
                    public boolean onTouch(View v, MotionEvent event) {
                        return gestureDetector.onTouchEvent(event);
                    }
                });

        }

我不确定这是一个完全好的答案,正如我之前提到的,您可以通过使用数组来改进这一点,在他的情况下调用每个视图同步的方法,在他的情况下只有 2.onFling 也被阻止而不是同步,如果您的滚动视图太长,这可能对用户不友好。最后,如果用户做了一个小动作,仍然会有一个小问题,但这是一种非常罕见的情况。

于 2015-11-13T18:33:59.207 回答