Как программно переместить вид горизонтальной прокрутки наполовину в Android?

#java #android #horizontal-scrolling #horizontalscrollview

#java #Android #горизонтальная прокрутка #horizontalscrollview

Вопрос:

В моем приложении для Android я создаю горизонтальный вид прокрутки, добавляю содержимое и добавляю его в DOM. Как я могу (используя java) переместить полосу прокрутки на половину пути?

Спасибо.

Этот код не работает

         Context context = carousel_container.getContext();

        HorizontalScrollView hsv = new HorizontalScrollView(context);
        LinearLayout carousel = new LinearLayout(context);
        setGallery(carousel);

        addFishes();

        hsv.addView(carousel, new HorizontalScrollView.LayoutParams(HorizontalScrollView.LayoutParams.WRAP_CONTENT, HorizontalScrollView.LayoutParams.WRAP_CONTENT));
        carousel_container.addView(hsv, new HorizontalScrollView.LayoutParams(HorizontalScrollView.LayoutParams.MATCH_PARENT, HorizontalScrollView.LayoutParams.WRAP_CONTENT));

        hsv.postDelayed(new Runnable(){
            @Override
            public void run() {
                int offsetX = hsv.getWidth()/2;
                //int offsetX = hsv.getMaxScrollAmount()/2;
                hsv.scrollTo(offsetX, 0);
             }
        }, 10000);
  

Комментарии:

1. В каком типе макета находится вид прокрутки?

2. Я добавляю горизонтальный вид прокрутки в вертикальный LinearLayout.

3. Вы пробовали hsv.scrollTo(hsv.getMaxScrollAmount()/ 2, 0); ?

4. Вероятно, вам следует добавить OnGlobalLayoutListener для прослушивания, когда HorizontalScrollView выложен. После этого вы можете вызвать getWidth() и выполнить hsv.scrollTo(hsv.getWidth()/2); , но не раньше, так как getWidth() вернет 0 до того, как представление будет выложено.

5. Я добавляю множество горизонтальных макетов динамически, не все одновременно, но это зависит от того, когда пользователь нажимает кнопку. Запускается ли ongloballayoutlistener каждый раз, когда я добавляю horizontalview?

Ответ №1:

Как уже указывал DeeV:

  1. Сначала нужно нарисовать макет. Только тогда ширина видов будет больше 0.
  2. Вы не можете использовать ширину HorizontalScrollViews для прокрутки к центру. Используйте ширину внутреннего вида (в вашем случае: карусель).

Если ваш HorizontalScrollView находится внутри Activity, используйте это, чтобы убедиться, что вид готов к прокрутке:

 @Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    // do scrolling here
}
  

Если ваш HorizontalScrollView находится внутри фрагмента, либо реализуйте обратный вызов для передачи фрагменту события «views-are-ready», либо используйте этот код, который повторяется до тех пор, пока это не произойдет:

 @Override
public void onResume() {
    super.onResume();
    final Handler mainThreadHandler = new Handler(Looper.getMainLooper());
    mainThreadHandler.post(new Runnable() {
        @Override
        public void run() {
            if (hsv.getWidth() > 0) {
                // do scrolling here
            } else {
                mainThreadHandler.post(this);
            }
        }
    });
}
  

Теперь к самой прокрутке. hsv.scrollTo(carousel.getWidth() / 2, 0) предлагается другими, но это не будет делать то, что вы хотите. Первым параметром scrollTo (…) является координата x текущего видимого левого края внутреннего вида (т. Е. Диапазон x-прокрутки HorizontalScrollView составляет от 0 до ширины внутреннего вида минус ширина HorizontalScrollView). Это означает, что с помощью carousel.getWidth() / 2 будет прокручиваться левый край экрана к центру вашего вида. Итак, если вы хотите прокрутить до центра вашего вида, вам следует использовать это вместо:

 hsv.scrollTo((carousel.getWidth() - hsv.getWidth()) / 2, 0);
  

Ответ №2:

Я думаю, что основная проблема, с которой вы сталкиваетесь, заключается в том, что ваши представления не раздуты и пока не имеют каких-либо размеров, поэтому ваш «scrollTo» всегда будет равен 0. Сначала вам нужно подождать, пока ScrollView и его содержимое не будут увеличены. Следующее, что вы не можете использовать ширину ScrollView, потому что это размер экрана. Вам нужно использовать дочерний элемент with (carousel), который не привязан (в качестве альтернативы вы можете использовать getMaxScrollAmount() ).

Самое простое, что можно сделать, это опубликовать в нем Runnable вот так:

 private class ScrollToCenter implements Runnable {
   @Override
   public void run() {
      hsv.scrollTo(carousel.getWidth()/2, 0);
   }
}

hsv.post(new ScrollToCenter());
  

Публикация в представлении будет ждать, пока представление не станет видимым, прежде чем выполнять. Если вид уже виден, то он будет выполнен почти немедленно.

Комментарии:

1. могу ли я передать параметры run() для представлений hsv и carousel?

2. Вам нужно было бы использовать конструктор для ScrollToCenter передачи параметров или использовать методы получения / установки.

3. Я обновил свой пост выше вашим кодом, но он по-прежнему не работал.

4. Я даже пытался hsv.scrollTo(hsv.getChildAt(0).getWidth()/2, 0); , и это не сработало.

5. ОК. Я только что внедрил решение в один из своих проектов, и оно действительно работает, но вам придется подождать, пока карусель не заполнится. Ваша карусель может быть выполнена не полностью, поэтому ее размер всегда равен 0. Вы можете проверить эту теорию, поменяв post местами с postDelayed() и установив задержку на 5000 миллисекунд. Кроме того, я использовал getMaxScrollAmount() , и это прокручивало его только по ширине ScrollView ; не его содержимое.