Как получить смещение в RecyclerView ItemDecorator



Я написал два ItemDecorator для RecyclerView. Каждый добавляет некоторое смещение сверху в getItemOffsets(). Скажем:




  • Первый декоратор добавляет 20dp смещение сверху

  • Второй декратор добавляет 30dp верхнее смещение


Теперь, когда я добавляю их оба в RecyclerView, каждый элемент корректно смещается на 50dp, это хорошо.

Но тут возникает вопрос:
Как мне получить это смещение в onDraw/onDrawOver?



Обычно декораторы рисуют свои вещи, пересекая parent.getChildAt(i) материал и получая child.getTop() для пример для рисования над дочерним видом RecyclerView.



Но в этом случае это смешало бы рисунок другого декоратора, потому что он также использовал бы child.getTop().

Таким образом, на данный момент кажется, что обоим декораторам нужно знать друг о друге и о росте друг друга.

Я что-то упустил? Надеюсь, что да.



Править: я сообщил о проблеме в Android issue tracker, и, похоже, это будет работать. Звезда его, чтобы следить за прогрессом: https://code.google.com/p/android/issues/detail?id=195746

599   1  

1 ответ:

tl; dr Нет, вы ничего не упускаете. Но вы можете получить значения, необходимые в getItemOffsets, хотя мне это кажется немного грязным.

В принципе есть только один вариант получения украшенной высоты, кроме управления украшениями самостоятельно: LayoutManager.getDecoratedTop();

OnDraw

В onDraw Вы получаете весь холст recyclerView, c.getClipBounds() не содержит никакой информации. Хотя джавадок добавления украшений говорит, что украшения должны просто нарисуйте в пределах их границ.

Кроме того, получение parent.getLayoutManager().getDecoratedTop() даст вам одинаковые значения в каждом украшении, так как здесь уже слишком поздно, эти значения предназначены для размещения.

Мы опоздали, разметка сделана, и мы ее пропустили.

GetItemOffsets

Пожалуйста, обратите внимание, что я протестировал следующее с LinearLayoutManager, и это может также не работать с другими (определенно не с большинством пользовательских). Так как я полагаюсь на измерение происходящего между этими вызовами, которое не документировано, данное решение может сломаться с некоторой будущей версией.
Я просто чувствовал, что мне нужно это опровержение. Я нашел рабочее решение (смотрите mOffset):
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
    mOffset = parent.getLayoutManager().getTopDecorationHeight(view);
    outRect.set(0, 10, 0, 0);
}

Это работает, потому что recyclerview, вычисляя общую вставку дочернего элемента, обновляет переменную local LayoutParams пакета представлений . Хотя мы не можем получить доступ к самой переменной параметра layout, вызов getTopDecorationHeight фактически использует (в настоящее время) грязную вставку, придавая нам надлежащее значение.
Таким образом, вы можете получить смещение предыдущих украшений, прежде чем применять свои собственные!

Чтобы применить его, просто удалите другие украшения смещение при рисовании вашего украшения:

c.drawRect(child.getLeft() + child.getTranslationX(),
        mOffset + layoutManager.getDecoratedTop(child) + child.getTranslationY(),
        child.getRight() + child.getTranslationX(),
        child.getBottom() + child.getTranslationY(), paint);

Это фактически применит смещение других украшений, а затем нарисуйте свое собственное из правильного верха.

Некоторые Проблемы

Теперь это основное, рабочее решение для по умолчанию usecase . но . Если у вас разные смещения в зависимости от типа элемента VIEW_TYPE или положения адаптера, все становится сложнее.

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

Чтобы сделать это, вы можете либо добавить какой-то пользовательский тег с view.setTag(key, object), либо сделать что-то подобное с объектом RecyclerView.State, который передается по кругу.

Comments

    Ничего не найдено.