Синхронизация двух видов горизонтальной прокрутки в Android - PullRequest
3 голосов
/ 24 октября 2011

Я пытался следовать совету из этого поста Синхронизировать позиции прокрутки ScrollView - android , но столкнулся с проблемой.

Фон - я хочу макет таблицы с горизонтальной и вертикальной прокруткой, но я хочу, чтобы первый ряд и первый столбец присутствовали всегда - как стоп-панель с Excel. К сожалению, кажется, что это почти невозможно с Java-программированием на Android ... вызывает у меня такую ​​головную боль. Я настроил его так, что, если я смогу просто синхронизировать эти два горизонтальных просмотра, тогда таблица будет работать так, как я хочу.

Я следовал совету из размещенной ссылки выше, и проблема у меня заключается в следующем. Приложение силы закрывается, когда я реализую

scrollView1.setScrollViewListener (это);

Мне кажется, проблема в том, как я объявляю ObservableScrollViews. Я не использую XML - все объекты создаются программно. Я пытался использовать

private ObservableScrollView oScrollViewOne = new ObservableScrollView (это);

но это также вызывает сближение сил. (Могу ли я просто создать обычный вид прокрутки, назначить ему идентификатор и затем использовать

scrollView1 = (ObservableScrollView) findViewById (ID); где ID - целое число, которое я дал просмотру прокрутки.

Мне интересно, что делать с комментариями ниже и как их использовать, если я не использую макет XML.

И мы должны указать этот новый класс ObservableScrollView в макете вместо существующих тегов ScrollView.

com.test.ObservableScrollView андроид: идентификатор = "@ + идентификатор / 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);
  }

Ответы [ 2 ]

5 голосов
/ 24 октября 2011

Ошибка указывает на нулевой указатель в конструкторе в ObservableScrollView. Не могли бы вы опубликовать конструктор, а также строку 12 самостоятельно?

Одна возможная проблема, с которой я сталкиваюсь при взаимодействии вашего XML и пользовательского представления прокрутки, заключается в том, что ваше пользовательское представление прокрутки является внутренним классом. См. на этой странице , чтобы узнать, как объявить собственный компонент внутреннего класса в XML или переместить его во внешний класс. Я обычно помещаю его во внешний класс, но если вы хотите сохранить его как внутренний класс, это будет что-то вроде

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

Я не думаю, что это объясняет ваше исключение нулевого указателя, поэтому, пожалуйста, опубликуйте свой класс ObservableScrollView.

EDIT:

Если вы настаиваете на том, чтобы делать все на 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 облегчает чтение. В любом случае, надеюсь, это прояснит ситуацию.

0 голосов
/ 13 ноября 2015

Это мое решение, дальнейшее объяснение в коде:

//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 вместо Будучи синхронизированным, если ваш вид прокрутки слишком длинный, это не может быть удобным для пользователя. И, наконец, есть небольшая проблема, если пользователь делает крошечные броски, но это очень редкий случай.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...