Масштабировать элемент в 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"
}
Обратите внимание на выключение на одну ошибку.