Масштабировать элемент в RecyclerView для перекрытия 2 смежных элементов Android

Я использую RecyclerView с GridLayoutManager. Цель, которую я хочу достичь, - это когда я нажимаю на элемент, он будет масштабироваться и перекрывать смежные элементы. Как и на картинке ниже (в Android TV) enter image description here

Когда событие onClick запускается, я вызываю

v.animate().scaleX(1.2f).scaleY(1.2f).setDuration(500).start();

Но результат ниже: enter image description here

Он может перекрывать только элементы, у которых положение ниже самого. Что делать, чтобы перекрывать все смежные элементы. Спасибо заранее. ИЗМЕНИТЬ
Я уже пробовал:

v.bringToFront();

или

(v.getParent()).bringChildToFront(v);

Но оба они не работают.

Ответ 1

В ответе aga я использую ViewCompat.setElevation(View view, float elevation) для поддержки API до 21, он работает как очаровательный.

static class ViewHolder extends RecyclerView.ViewHolder {

  public ViewHolder(View root) {
    // bind views
    // ...

    // bind focus listener
    root.setOnFocusChangeListener(new View.OnFocusChangeListener() {
      @Override
        public void onFocusChange(View v, boolean hasFocus) {
          if (hasFocus) {
            // run scale animation and make it bigger

            ViewCompat.setElevation(root, 1);
          } else {
            // run scale animation and make it smaller

            ViewCompat.setElevation(root, 0);
          }
        }
     });
  }
}

Файл макета элемента очень прост, как показано ниже:

<?xml version="1.0" encoding="utf-8"?>
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:background="@drawable/sl_live_item" />

Ответ 2

1. Вернуть метод getChildDrawingOrder.

@Override
protected int getChildDrawingOrder(int childCount, int i) {
    View view = getLayoutManager().getFocusedChild();
    if (null == view) {
        return super.getChildDrawingOrder(childCount, i);
    }
    int position = indexOfChild(view);

    if (position < 0) {
        return super.getChildDrawingOrder(childCount, i);
    }
    if (i == childCount - 1) {
        return position;
    }
    if (i == position) {
        return childCount - 1;
    }
    return super.getChildDrawingOrder(childCount, i);
}

2.RecyclerView setChildrenDrawingOrderEnabled true.

setChildrenDrawingOrderEnabled(true);

3. Когда в представлении элемента есть фокус, сделать недействительным его родительский.

@Override
public void onFocusChange(View v, boolean hasFocus) {
    if (hasFocus) {
        v.setScaleX(1.5f);
        v.setScaleY(1.5f);
        mRecyclerView.invalidate();
    } else {
        v.setScaleX(1.0f);
        v.setScaleY(1.0f);
    }
}

Ответ 3

Попробуйте вызвать v.bringToFront() перед запуском анимации.
Если это не работает, другой вариант - использовать View#setElevation(float val), где val > 0. Недостатком является то, что вам нужно будет установить возвышение до 0, когда вы отмените выбор элемента.

Ответ 4

Вам нужно сделать это по-старому, как вы это делаете, с обычными ViewGroups, переопределяя порядок рисования детей. Этот пример заставляет первое представление всегда рисоваться последним - вам нужно настроить его для использования.

public TopForcingRecyclerView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    setChildrenDrawingOrderEnabled(true);
}

@Override protected int getChildDrawingOrder(int childCount, int i) {
    if (i >= childCount - 1) return 0; 
    //when asked for the last view to draw, answer ZERO
    else return i + 1;
    //when asked for the i-th view to draw, answer "the next one"
}

Обратите внимание на выключение на одну ошибку.