Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RecyclerView items lose focus

In my fire tv app I'm using a recyclerview with horizontal layout.

Scrolling with dpad works and also items are gaining focus.

But when I hold the button it scrolls very fast because many keydown events are triggered, and items are losing their focus and it's not possible to scroll anymore because another Textview above my recyclerview is gaining the focus.

It looks like a bug. Is there any workaround for this?

like image 957
pawlinsky Avatar asked Dec 14 '15 22:12

pawlinsky


People also ask

How do I remove focus from RecyclerView?

Check out clearFocus() from here Android Dev Doc. You can set a DrawerListener to your navigation drawer and use the onDrawerStateChanged() or some of the other options from here to call clearFocus() on your RecyclerView.

How do I use DiffUtil on Android?

Stay organized with collections Save and categorize content based on your preferences. DiffUtil is a utility class that calculates the difference between two lists and outputs a list of update operations that converts the first list into the second one. It can be used to calculate updates for a RecyclerView Adapter.


2 Answers

I face the same problem, what i do in my project likes below in my Activity (containing RecyclerView):

    private long mLastKeyDownTime = 0;
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        long current = System. currentTimeMillis();
        boolean res = false;
        if (current - mLastKeyDownTime < 300 ) {
            res = true;
        } else {
            res = super.onKeyDown(keyCode, event);
            mLastKeyDownTime = current;
        }
        return res;
    }

which avoids the fast scrolling when you hold the button on the dpad, and the focus works fine in my RecyclerView.

like image 138
Xiaozou Avatar answered Oct 21 '22 22:10

Xiaozou


I think the answer by @tmm1 is the best one so far. I have successfully implemented this workaround for the issue of elements loaded in a RecyclerView loosing focus if user uses the DPAD too quickly to scroll.

In my RecyclerView's adapter I use a LayoutInflater to inflate my element views like this

@Override
public ListItemViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
    View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_keyboard_key, viewGroup, false);
    return new ListItemViewHolder(itemView);
}

My item_keyboard_key.xml were originally defined like this

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/item_keyboard_key_layout"
    android:orientation="vertical"
    android:gravity="center"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/item_keyboard_key_text"
        android:text="A"/>

</FrameLayout>

Then I created a new custom FrameLayout class (FocusFixFrameLayout) extending FrameLayout and using this as my root layout. My item_keyboard_key.xml then became

<?xml version="1.0" encoding="utf-8"?>
<no.bluebit.views.FocusFixFrameLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/item_keyboard_key_layout"
    android:orientation="vertical"
    android:gravity="center"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/item_keyboard_key_text"
        android:text="A"/>

</no.bluebit.views.FocusFixFrameLayout>

and my FocusFixFrameLayout class looks like this

public class FocusFixFrameLayout extends FrameLayout {

    public FocusFixFrameLayout(@NonNull Context context) {
        super(context);
    }

    public FocusFixFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public FocusFixFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public FocusFixFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
}

    @Override
    public void clearFocus() {
        if(this.getParent() != null)
            super.clearFocus();
    }
}
like image 8
Håvard Bakke Avatar answered Oct 21 '22 22:10

Håvard Bakke