10

У меня есть одно вертикальное вложенное scrollview, которое содержит кучу recyclerview с горизонтальной установкой layoutmanager. Идея довольно похожа на то, как выглядит новый игровой магазин google. Я могу сделать его функциональным, но он не является гладким. Вот проблемы:NestedScrollView и горизонтальный RecyclerView Smooth Scrolling

1) Объект горизонтального возврата не может перехватить событие касания большую часть времени, даже если я коснусь его. Кажется, что представление прокрутки имеет приоритет для большинства движений. Мне трудно зацепиться за горизонтальное движение. Этот UX разочаровывает, поскольку мне нужно попробовать несколько раз, прежде чем он сработает. Если вы проверите магазин воспроизведения, он сможет очень хорошо перехватить событие касания, и он работает хорошо. Я заметил в игровом магазине то, как они его устанавливали, - это много горизонтальных переработок внутри одного вертикального рециклинга. Нет прокрутки.

2) Высота горизонтальных recyclerviews должна быть установлена ​​вручную, и нет простого способа рассчитать высоту элементов для детей.

Вот макет, я использую:

<android.support.v4.widget.NestedScrollView 
    android:id="@+id/scroll" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:clipToPadding="false" 
    android:background="@color/dark_bgd" 
    app:layout_behavior="@string/appbar_scrolling_view_behavior"> 

    <LinearLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:orientation="vertical"> 

     <LinearLayout 
      android:id="@+id/main_content_container" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:visibility="gone" 
      tools:visibility="gone" 
      android:orientation="vertical">     

       <android.support.v7.widget.RecyclerView 
        android:id="@+id/starring_list" 
        android:paddingLeft="@dimen/spacing_major" 
        android:paddingRight="@dimen/spacing_major" 
        android:layout_width="match_parent" 
        android:layout_height="180dp" /> 

Эта модель пользовательского интерфейса является очень простой и, скорее всего, используется во многих приложениях. Я прочитал много SO, где ppl заявляет, что это плохая идея поместить список в список, но это очень распространенный и современный шаблон пользовательского интерфейса, используемый повсеместно. Принимая во внимание netflix-интерфейс с серией горизонтальных списков прокрутки внутри вертикальный список. Разве нет гладкого пути для этого?

Пример изображение из магазина:

Google Play Store

+0

Странно то, что у меня есть противоположная проблема: я хочу, чтобы NestedScrollView позволял прокручивать по вертикали, но горизонтальный RecyclerView принимает события касания, поэтому, когда я запускаю вертикальную прокрутку на нем, он не позволяет этого. Кроме того, кстати, если у вас есть всего несколько элементов для показа, вы можете использовать простой HorizontalScrollView с LinearLayout. –

ответ

13

Итак, проблема с гладкой прокруткой исправлена. Это было вызвано ошибкой в ​​NestedScrollView в Библиотеке поддержки дизайна (в настоящее время 23.1.1).

Вы можете прочитать о проблеме и просто исправить здесь: https://code.google.com/p/android/issues/detail?id=194398

Короче говоря, после того, как вы выполнили бросок, то nestedscrollview не регистрировал полный на компоненте скроллера и поэтому требуется дополнительный ' ACTION_DOWN 'для освобождения родительского вложенного scrollview от перехвата (съедания) последующих событий. Итак, что случилось, если вы пробовали прокручивать свой дочерний список (или просмотрщик), после переброски первый штрих освобождает родительское связывание NSV, и последующие штрихи будут работать. Это делало UX очень плохим.

По существу нужно добавить эту строку на ACTION_DOWN случае НСВ:

computeScroll(); 

Вот что я использую:

public class MyNestedScrollView extends NestedScrollView { 
private int slop; 
private float mInitialMotionX; 
private float mInitialMotionY; 

public MyNestedScrollView(Context context) { 
    super(context); 
    init(context); 
} 

private void init(Context context) { 
    ViewConfiguration config = ViewConfiguration.get(context); 
    slop = config.getScaledEdgeSlop(); 
} 

public MyNestedScrollView(Context context, AttributeSet attrs) { 
    super(context, attrs); 
    init(context); 
} 

public MyNestedScrollView(Context context, AttributeSet attrs, int defStyleAttr) { 
    super(context, attrs, defStyleAttr); 
    init(context); 
} 


private float xDistance, yDistance, lastX, lastY; 

@Override 
public boolean onInterceptTouchEvent(MotionEvent ev) { 
    final float x = ev.getX(); 
    final float y = ev.getY(); 
    switch (ev.getAction()) { 
     case MotionEvent.ACTION_DOWN: 
      xDistance = yDistance = 0f; 
      lastX = ev.getX(); 
      lastY = ev.getY(); 

      // This is very important line that fixes 
      computeScroll(); 


      break; 
     case MotionEvent.ACTION_MOVE: 
      final float curX = ev.getX(); 
      final float curY = ev.getY(); 
      xDistance += Math.abs(curX - lastX); 
      yDistance += Math.abs(curY - lastY); 
      lastX = curX; 
      lastY = curY; 

      if (xDistance > yDistance) { 
       return false; 
      } 
    } 


    return super.onInterceptTouchEvent(ev); 
} 

}

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

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

+0

Это сработало! Благодаря! – Sam

1

Я преуспел в этом горизонтальную прокрутку в вертикально прокрутке родителя с ViewPager:

<android.support.v4.widget.NestedScrollView 

    ... 

    <android.support.v4.view.ViewPager 
     android:id="@+id/pager_known_for" 
     android:layout_width="match_parent" 
     android:layout_height="350dp" 
     android:minHeight="350dp" 
     android:paddingLeft="24dp" 
     android:paddingRight="24dp" 
     android:clipToPadding="false"/> 

общественного класс UniversityKnownForPagerAdapter расширяет PagerAdapter {

public UniversityKnownForPagerAdapter(Context context) { 
    mContext = context; 
    mInflater = LayoutInflater.from(mContext); 
} 

@Override 
public Object instantiateItem(ViewGroup container, int position) { 
    View rootView = mInflater.inflate(R.layout.card_university_demographics, container, false); 

    ... 

    container.addView(rootView); 

    return rootView; 
} 

@Override 
public void destroyItem(ViewGroup container, int position, Object object) { 
    container.removeView((View)object); 
} 

@Override 
public int getCount() { 
    return 4; 
} 

@Override 
public boolean isViewFromObject(View view, Object object) { 
    return (view == object); 
} 

Только выпуск: вы должны указать фиксированную высоту для пейджера представления

+0

Спасибо за ваш ответ. Я тоже попробовал ваше решение и запустил просмотрщик и прокрутку, но те же проблемы прокрутки, о которых я говорил выше, тоже здесь. См. Мой ответ на исправление. – falc0nit3

+0

Вы пытались использовать viewpager вместо recyclerview? –

+0

Я сделал, это все еще не перехватывало события слишком хорошо. Проблема не в реализации дочерних списков (Recyclerview/Viewpager/HorizontalListView и т. Д.), Я думаю, а скорее в библиотеке NestedScrollView. (как я уже упоминал в своем ответе выше) – falc0nit3

Смежные вопросы