在Android中同步两个水平滚动视图

时间:2011-10-24 01:25:07

标签: android synchronize horizontalscrollview

我尝试按照这篇文章Synchronise ScrollView scroll positions - android的建议,但遇到了问题。

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

我按照上面发布的链接的建议,我遇到的问题是这个。 当我实现

时,应用程序强制关闭
  

scrollView1.setScrollViewListener(本);

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

  

private ObservableScrollView oScrollViewOne = new ObservableScrollView(this);

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

  

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

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

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

  

com.test.ObservableScrollView   机器人:ID = “@ + ID / scrollview1”   ......

     

使用显式代码实现同步两个horizo​​ntalscroll视图的任何其他建议 - 不仅仅是建议使用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);
  }

2 个答案:

答案 0 :(得分:5)

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

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

<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形式使其更易于阅读。无论如何,希望这可以解决问题。

答案 1 :(得分:0)

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

//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而不是同步,如果您的滚动视图太长,这可能不是用户友好的。最后,如果用户做了一次微小的甩尾,仍然存在问题,但这是一个非常罕见的情况。